Skip to content

Feature/ttl index #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Aug 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
30 changes: 16 additions & 14 deletions src/main/java/com/arangodb/ArangoCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,15 @@
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.
*
* @see <a href="https://docs.arangodb.com/current/HTTP/Collection/">Collection API Documentation</a>
* @see <a href="https://docs.arangodb.com/current/HTTP/Collection/">Documents API Documentation</a>
* @author Mark Vollmary
* @author Heiko Kernbach
*/
public interface ArangoCollection extends ArangoSerializationAccessor {

Expand Down Expand Up @@ -561,6 +549,20 @@ <T> MultiDocumentEntity<DocumentDeleteEntity<T>> deleteDocuments(
*/
IndexEntity ensureFulltextIndex(Iterable<String> fields, FulltextIndexOptions options) throws ArangoDBException;

/**
* Creates a ttl index for the collection, if it does not already exist.
*
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-ttl.html">API
* Documentation</a>
* @param fields
* A list of attribute paths
* @param options
* Additional options, can be null
* @return information about the index
* @throws ArangoDBException
*/
IndexEntity ensureTtlIndex(Iterable<String> fields, TtlIndexOptions options) throws ArangoDBException;

/**
* Fetches a list of all indexes on this collection.
*
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/arangodb/entity/IndexEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -90,6 +91,10 @@ public Boolean getGeoJson() {
return geoJson;
}

public Integer getExpireAfter() {
return expireAfter;
}

public Boolean getConstraint() {
return constraint;
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/arangodb/entity/IndexType.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
23 changes: 9 additions & 14 deletions src/main/java/com/arangodb/internal/ArangoCollectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

/**
Expand Down Expand Up @@ -131,10 +118,12 @@ public Collection<DocumentImportEntity> 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;
}

Expand Down Expand Up @@ -334,6 +323,12 @@ public IndexEntity ensureFulltextIndex(final Iterable<String> fields, final Full
return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class);
}

@Override
public IndexEntity ensureTtlIndex(final Iterable<String> fields, final TtlIndexOptions options)
throws ArangoDBException {
return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
}

@Override
public Collection<IndexEntity> getIndexes() throws ArangoDBException {
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());
Expand Down
26 changes: 9 additions & 17 deletions src/main/java/com/arangodb/internal/InternalArangoCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -654,6 +638,14 @@ protected Request createFulltextIndexRequest(final Iterable<String> fields, fina
return request;
}

protected Request createTtlIndexRequest(final Iterable<String> 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);
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/arangodb/model/OptionsBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> fields) {
return options.fields(fields);
}

public static CollectionCreateOptions build(final CollectionCreateOptions options, final String name) {
return options.name(name);
}
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/com/arangodb/model/TtlIndexOptions.java
Original file line number Diff line number Diff line change
@@ -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 <a href="https://www.arangodb.com/docs/stable/http/indexes-ttl.html">API Documentation</a>
*/
public class TtlIndexOptions extends IndexOptions {

private Iterable<String> fields;
private final IndexType type = IndexType.ttl;
private Integer expireAfter;

public TtlIndexOptions() {
super();
}

protected Iterable<String> getFields() {
return fields;
}

/**
* @param fields A list of attribute paths
* @return options
*/
protected TtlIndexOptions fields(final Iterable<String> 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;
}

}
38 changes: 38 additions & 0 deletions src/test/java/com/arangodb/ArangoCollectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,44 @@ public void createFulltextIndexWithOptions() {
assertThat(indexResult.getName(), is("myFulltextIndex"));
}

@Test
public void createTtlIndexWithoutOptions() {
if (!requireVersion(3, 5)) {
return;
}
final Collection<String> fields = new ArrayList<String>();
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<String> fields = new ArrayList<String>();
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<String> fields = new ArrayList<String>();
Expand Down
15 changes: 9 additions & 6 deletions src/test/java/com/arangodb/ArangoDBTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down