diff --git a/ChangeLog.md b/ChangeLog.md
index d866472bd..40bf7228d 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
### Added
- added support for named indices
+- added support for TTL indices
- added minReplicationAttribute for collections and graphs
- added batched thread support in ArangoCollection.importDocuments (by @rkhaja)
diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/src/main/java/com/arangodb/ArangoCollection.java
index b00f8b6dc..7ece5889d 100644
--- a/src/main/java/com/arangodb/ArangoCollection.java
+++ b/src/main/java/com/arangodb/ArangoCollection.java
@@ -32,20 +32,7 @@
import com.arangodb.entity.IndexEntity;
import com.arangodb.entity.MultiDocumentEntity;
import com.arangodb.entity.Permissions;
-import com.arangodb.model.CollectionCreateOptions;
-import com.arangodb.model.CollectionPropertiesOptions;
-import com.arangodb.model.DocumentCreateOptions;
-import com.arangodb.model.DocumentDeleteOptions;
-import com.arangodb.model.DocumentExistsOptions;
-import com.arangodb.model.DocumentImportOptions;
-import com.arangodb.model.DocumentReadOptions;
-import com.arangodb.model.DocumentReplaceOptions;
-import com.arangodb.model.DocumentUpdateOptions;
-import com.arangodb.model.FulltextIndexOptions;
-import com.arangodb.model.GeoIndexOptions;
-import com.arangodb.model.HashIndexOptions;
-import com.arangodb.model.PersistentIndexOptions;
-import com.arangodb.model.SkiplistIndexOptions;
+import com.arangodb.model.*;
/**
* Interface for operations on ArangoDB collection level.
@@ -53,6 +40,7 @@
* @see Collection API Documentation
* @see Documents API Documentation
* @author Mark Vollmary
+ * @author Heiko Kernbach
*/
public interface ArangoCollection extends ArangoSerializationAccessor {
@@ -561,6 +549,20 @@ MultiDocumentEntity> deleteDocuments(
*/
IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options) throws ArangoDBException;
+ /**
+ * Creates a ttl index for the collection, if it does not already exist.
+ *
+ * @see API
+ * Documentation
+ * @param fields
+ * A list of attribute paths
+ * @param options
+ * Additional options, can be null
+ * @return information about the index
+ * @throws ArangoDBException
+ */
+ IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options) throws ArangoDBException;
+
/**
* Fetches a list of all indexes on this collection.
*
diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/src/main/java/com/arangodb/entity/IndexEntity.java
index 0a11fbe06..201396e09 100644
--- a/src/main/java/com/arangodb/entity/IndexEntity.java
+++ b/src/main/java/com/arangodb/entity/IndexEntity.java
@@ -40,6 +40,7 @@ public class IndexEntity implements Entity {
private Boolean geoJson;
private Boolean constraint;
private Boolean deduplicate;
+ private Integer expireAfter;
private Boolean inBackground;
public IndexEntity() {
@@ -90,6 +91,10 @@ public Boolean getGeoJson() {
return geoJson;
}
+ public Integer getExpireAfter() {
+ return expireAfter;
+ }
+
public Boolean getConstraint() {
return constraint;
}
diff --git a/src/main/java/com/arangodb/entity/IndexType.java b/src/main/java/com/arangodb/entity/IndexType.java
index b08f0a3d5..1507ec3d8 100644
--- a/src/main/java/com/arangodb/entity/IndexType.java
+++ b/src/main/java/com/arangodb/entity/IndexType.java
@@ -22,8 +22,9 @@
/**
* @author Mark Vollmary
+ * @author Heiko Kernbach
*
*/
public enum IndexType {
- primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge
+ primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl
}
diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java
index 4fda706c6..690e8f43f 100644
--- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java
+++ b/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java
@@ -32,6 +32,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.arangodb.model.*;
import com.arangodb.ArangoCollection;
import com.arangodb.ArangoDBException;
import com.arangodb.entity.CollectionEntity;
@@ -45,20 +46,6 @@
import com.arangodb.entity.MultiDocumentEntity;
import com.arangodb.entity.Permissions;
import com.arangodb.internal.util.DocumentUtil;
-import com.arangodb.model.CollectionCreateOptions;
-import com.arangodb.model.CollectionPropertiesOptions;
-import com.arangodb.model.DocumentCreateOptions;
-import com.arangodb.model.DocumentDeleteOptions;
-import com.arangodb.model.DocumentExistsOptions;
-import com.arangodb.model.DocumentImportOptions;
-import com.arangodb.model.DocumentReadOptions;
-import com.arangodb.model.DocumentReplaceOptions;
-import com.arangodb.model.DocumentUpdateOptions;
-import com.arangodb.model.FulltextIndexOptions;
-import com.arangodb.model.GeoIndexOptions;
-import com.arangodb.model.HashIndexOptions;
-import com.arangodb.model.PersistentIndexOptions;
-import com.arangodb.model.SkiplistIndexOptions;
import com.arangodb.velocypack.VPackSlice;
/**
@@ -131,10 +118,12 @@ public Collection importDocuments(Collection> values, Do
try {
documentImportEntity = completableFuture.get();
} catch (InterruptedException | ExecutionException e) {
+ executorService.shutdown();
throw new ArangoDBException(e);
}
documentImportEntityList.add(documentImportEntity);
}
+ executorService.shutdown();
return documentImportEntityList;
}
@@ -334,6 +323,12 @@ public IndexEntity ensureFulltextIndex(final Iterable fields, final Full
return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class);
}
+ @Override
+ public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options)
+ throws ArangoDBException {
+ return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
+ }
+
@Override
public Collection getIndexes() throws ArangoDBException {
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());
diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java
index 1aee8ace9..310cc023a 100644
--- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java
+++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java
@@ -39,23 +39,7 @@
import com.arangodb.internal.util.ArangoSerializationFactory.Serializer;
import com.arangodb.internal.util.DocumentUtil;
import com.arangodb.internal.util.RequestUtils;
-import com.arangodb.model.CollectionPropertiesOptions;
-import com.arangodb.model.CollectionRenameOptions;
-import com.arangodb.model.DocumentCreateOptions;
-import com.arangodb.model.DocumentDeleteOptions;
-import com.arangodb.model.DocumentExistsOptions;
-import com.arangodb.model.DocumentImportOptions;
-import com.arangodb.model.DocumentReadOptions;
-import com.arangodb.model.DocumentReplaceOptions;
-import com.arangodb.model.DocumentUpdateOptions;
-import com.arangodb.model.FulltextIndexOptions;
-import com.arangodb.model.GeoIndexOptions;
-import com.arangodb.model.HashIndexOptions;
-import com.arangodb.model.ImportType;
-import com.arangodb.model.OptionsBuilder;
-import com.arangodb.model.PersistentIndexOptions;
-import com.arangodb.model.SkiplistIndexOptions;
-import com.arangodb.model.UserAccessOptions;
+import com.arangodb.model.*;
import com.arangodb.util.ArangoSerializer;
import com.arangodb.velocypack.Type;
import com.arangodb.velocypack.VPackSlice;
@@ -654,6 +638,14 @@ protected Request createFulltextIndexRequest(final Iterable fields, fina
return request;
}
+ protected Request createTtlIndexRequest(final Iterable fields, final TtlIndexOptions options) {
+ final Request request = request(db.name(), RequestType.POST, PATH_API_INDEX);
+ request.putQueryParam(COLLECTION, name);
+ request.setBody(
+ util().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields)));
+ return request;
+ }
+
protected Request getIndexesRequest() {
final Request request = request(db.name(), RequestType.GET, PATH_API_INDEX);
request.putQueryParam(COLLECTION, name);
diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/src/main/java/com/arangodb/model/OptionsBuilder.java
index 5c348cfb7..7c5e92e58 100644
--- a/src/main/java/com/arangodb/model/OptionsBuilder.java
+++ b/src/main/java/com/arangodb/model/OptionsBuilder.java
@@ -62,6 +62,10 @@ public static FulltextIndexOptions build(final FulltextIndexOptions options, fin
return options.fields(fields);
}
+ public static TtlIndexOptions build(final TtlIndexOptions options, final Iterable fields) {
+ return options.fields(fields);
+ }
+
public static CollectionCreateOptions build(final CollectionCreateOptions options, final String name) {
return options.name(name);
}
diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/src/main/java/com/arangodb/model/TtlIndexOptions.java
new file mode 100644
index 000000000..45a8ff3e9
--- /dev/null
+++ b/src/main/java/com/arangodb/model/TtlIndexOptions.java
@@ -0,0 +1,69 @@
+/*
+ * DISCLAIMER
+ *
+ * Copyright 2019 ArangoDB GmbH, Cologne, Germany
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright holder is ArangoDB GmbH, Cologne, Germany
+ */
+
+package com.arangodb.model;
+
+import com.arangodb.entity.IndexType;
+
+/**
+ * @author Heiko Kernbach
+ * @see API Documentation
+ */
+public class TtlIndexOptions extends IndexOptions {
+
+ private Iterable fields;
+ private final IndexType type = IndexType.ttl;
+ private Integer expireAfter;
+
+ public TtlIndexOptions() {
+ super();
+ }
+
+ protected Iterable getFields() {
+ return fields;
+ }
+
+ /**
+ * @param fields A list of attribute paths
+ * @return options
+ */
+ protected TtlIndexOptions fields(final Iterable fields) {
+ this.fields = fields;
+ return this;
+ }
+
+ protected IndexType getType() {
+ return type;
+ }
+
+ /**
+ * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as “expired”.
+ * @return options
+ */
+ public TtlIndexOptions expireAfter(final Integer expireAfter) {
+ this.expireAfter = expireAfter;
+ return this;
+ }
+
+ protected Integer getExpireAfter() {
+ return expireAfter;
+ }
+
+}
diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java
index e1d3ac565..17908f3d1 100644
--- a/src/test/java/com/arangodb/ArangoCollectionTest.java
+++ b/src/test/java/com/arangodb/ArangoCollectionTest.java
@@ -1288,6 +1288,44 @@ public void createFulltextIndexWithOptions() {
assertThat(indexResult.getName(), is("myFulltextIndex"));
}
+ @Test
+ public void createTtlIndexWithoutOptions() {
+ if (!requireVersion(3, 5)) {
+ return;
+ }
+ final Collection fields = new ArrayList();
+ fields.add("a");
+ try {
+ final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureTtlIndex(fields, null);
+ } catch (final ArangoDBException e) {
+ assertThat(e.getResponseCode(), is(400));
+ assertThat(e.getErrorNum(), is(10));
+ assertThat(e.getMessage(), containsString("expireAfter attribute must be a number"));
+ }
+ }
+
+ @Test
+ public void createTtlIndexWithOptions() {
+ if (!requireVersion(3, 5)) {
+ return;
+ }
+ final Collection fields = new ArrayList();
+ fields.add("a");
+
+ final TtlIndexOptions options = new TtlIndexOptions();
+ options.name("myTtlIndex");
+ options.expireAfter(3600);
+
+ final IndexEntity indexResult = db.collection(COLLECTION_NAME).ensureTtlIndex(fields, options);
+ assertThat(indexResult, is(notNullValue()));
+ assertThat(indexResult.getFields(), hasItem("a"));
+ assertThat(indexResult.getId(), startsWith(COLLECTION_NAME));
+ assertThat(indexResult.getIsNewlyCreated(), is(true));
+ assertThat(indexResult.getType(), is(IndexType.ttl));
+ assertThat(indexResult.getExpireAfter(), is(3600));
+ assertThat(indexResult.getName(), is("myTtlIndex"));
+ }
+
@Test
public void getIndexes() {
final Collection fields = new ArrayList();
diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java
index 0a243656c..49cfbf906 100644
--- a/src/test/java/com/arangodb/ArangoDBTest.java
+++ b/src/test/java/com/arangodb/ArangoDBTest.java
@@ -441,17 +441,20 @@ public void loadproperties2() {
@Test
public void accessMultipleDatabases() {
+ String db1 = "multipledb1";
+ String db2 = "multipledb2";
+
try {
- arangoDB.createDatabase("db1");
- arangoDB.createDatabase("db2");
+ arangoDB.createDatabase(db1);
+ arangoDB.createDatabase(db2);
- final ArangoDBVersion version1 = arangoDB.db("db1").getVersion();
+ final ArangoDBVersion version1 = arangoDB.db(db1).getVersion();
assertThat(version1, is(notNullValue()));
- final ArangoDBVersion version2 = arangoDB.db("db2").getVersion();
+ final ArangoDBVersion version2 = arangoDB.db(db2).getVersion();
assertThat(version2, is(notNullValue()));
} finally {
- arangoDB.db("db1").drop();
- arangoDB.db("db2").drop();
+ arangoDB.db(db1).drop();
+ arangoDB.db(db2).drop();
}
}