Skip to content
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

[DE-80] zkd indexes #417

Merged
merged 4 commits into from
Jan 12, 2022
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
13 changes: 13 additions & 0 deletions src/main/java/com/arangodb/ArangoCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,19 @@ <T> MultiDocumentEntity<DocumentDeleteEntity<T>> deleteDocuments(
*/
IndexEntity ensureTtlIndex(Iterable<String> fields, TtlIndexOptions options) throws ArangoDBException;

/**
* Creates a ZKD multi-dimensional index for the collection, if it does not already exist.
* Note that zkd indexes are an experimental feature in ArangoDB 3.9.
*
* @param fields A list of attribute paths
* @param options Additional options, can be null
* @return information about the index
* @throws ArangoDBException
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-multi-dim.html">API Documentation</a>
* @since ArangoDB 3.9
*/
IndexEntity ensureZKDIndex(Iterable<String> fields, ZKDIndexOptions options) throws ArangoDBException;

/**
* Fetches a list of all indexes on this collection.
*
Expand Down
20 changes: 16 additions & 4 deletions src/main/java/com/arangodb/async/ArangoCollectionAsync.java
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ <T> CompletableFuture<DocumentUpdateEntity<T>> updateDocument(
* to patch (the patch document). All attributes from the patch document will be added to the existing document if
* they do not yet exist, and overwritten in the existing document if they do exist there.
*
* @param key The key of the document
* @param value A representation of a single document (POJO, VPackSlice or String for Json)
* @param options Additional options, can be null
* @param returnType Type of the returned newDocument and/or oldDocument
* @param key The key of the document
* @param value A representation of a single document (POJO, VPackSlice or String for Json)
* @param options Additional options, can be null
* @param returnType Type of the returned newDocument and/or oldDocument
* @return information about the document
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-document">API
* Documentation</a>
Expand Down Expand Up @@ -497,6 +497,18 @@ CompletableFuture<IndexEntity> ensureFulltextIndex(
*/
CompletableFuture<IndexEntity> ensureTtlIndex(Iterable<String> fields, TtlIndexOptions options);

/**
* Creates a ZKD multi-dimensional index for the collection, if it does not already exist.
* Note that zkd indexes are an experimental feature in ArangoDB 3.9.
*
* @param fields A list of attribute paths
* @param options Additional options, can be null
* @return information about the index
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-multi-dim.html">API Documentation</a>
* @since ArangoDB 3.9
*/
CompletableFuture<IndexEntity> ensureZKDIndex(final Iterable<String> fields, final ZKDIndexOptions options);

/**
* Returns all indexes of the collection
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ public CompletableFuture<IndexEntity> ensureTtlIndex(Iterable<String> fields, Tt
return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
}

@Override
public CompletableFuture<IndexEntity> ensureZKDIndex(
final Iterable<String> fields,
final ZKDIndexOptions options) {
return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class);
}

@Override
public CompletableFuture<Collection<IndexEntity>> getIndexes() {
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/arangodb/entity/IndexType.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
* @author Heiko Kernbach
*/
public enum IndexType {
primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl
primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl, zkd
}
6 changes: 6 additions & 0 deletions src/main/java/com/arangodb/internal/ArangoCollectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ public IndexEntity ensureTtlIndex(final Iterable<String> fields, final TtlIndexO
return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
}

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

@Override
public Collection<IndexEntity> getIndexes() throws ArangoDBException {
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,15 @@ protected Request createTtlIndexRequest(final Iterable<String> fields, final Ttl
return request;
}

protected Request createZKDIndexRequest(
final Iterable<String> fields, final ZKDIndexOptions options) {
final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX);
request.putQueryParam(COLLECTION, name);
request.setBody(util().serialize(OptionsBuilder.build(options != null ? options :
new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields)));
return request;
}

protected Request getIndexesRequest() {
final Request request = request(db.dbName(), RequestType.GET, PATH_API_INDEX);
request.putQueryParam(COLLECTION, name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer;
import com.arangodb.entity.arangosearch.analyzer.TextAnalyzer;
import com.arangodb.model.CollectionSchema;
import com.arangodb.model.ZKDIndexOptions;
import com.arangodb.velocypack.VPackDeserializer;
import com.arangodb.velocypack.VPackParser;
import com.arangodb.velocypack.VPackSlice;
Expand Down Expand Up @@ -332,4 +333,8 @@ protected static FieldLink deserializeField(final Entry<String, VPackSlice> fiel
return collectionValidation;
};

public static final VPackDeserializer<ZKDIndexOptions.FieldValueTypes> ZKD_FIELD_VALUE_TYPES =
(parent, vpack, context) -> ZKDIndexOptions.FieldValueTypes.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH));


}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest;
import com.arangodb.model.CollectionSchema;
import com.arangodb.model.TraversalOptions;
import com.arangodb.model.ZKDIndexOptions;
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
import com.arangodb.velocypack.VPackModule;
import com.arangodb.velocypack.VPackParserModule;
Expand Down Expand Up @@ -70,6 +71,7 @@ public <C extends VPackSetupContext<C>> void setup(final C context) {
context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES);
context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE);
context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION);
context.registerSerializer(ZKDIndexOptions.FieldValueTypes.class, VPackSerializers.ZKD_FIELD_VALUE_TYPES);

context.registerDeserializer(Response.class, VPackDeserializers.RESPONSE);
context.registerDeserializer(CollectionType.class, VPackDeserializers.COLLECTION_TYPE);
Expand All @@ -89,6 +91,7 @@ public <C extends VPackSetupContext<C>> void setup(final C context) {
context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY);
context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE);
context.registerDeserializer(CollectionSchema.class, VPackDeserializers.COLLECTION_VALIDATION);
context.registerDeserializer(ZKDIndexOptions.FieldValueTypes.class, VPackDeserializers.ZKD_FIELD_VALUE_TYPES);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.arangodb.model.CollectionSchema;
import com.arangodb.model.TraversalOptions;
import com.arangodb.model.TraversalOptions.Order;
import com.arangodb.model.ZKDIndexOptions;
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
import com.arangodb.velocypack.VPackBuilder;
import com.arangodb.velocypack.VPackParser;
Expand Down Expand Up @@ -285,4 +286,7 @@ private static void serializeFieldLinks(final VPackBuilder builder, final Collec
context.serialize(builder, attribute, doc);
};

public static final VPackSerializer<ZKDIndexOptions.FieldValueTypes> ZKD_FIELD_VALUE_TYPES =
(builder, attribute, value, context) -> builder.add(attribute, value.name().toLowerCase(Locale.ENGLISH));

}
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 @@ -65,6 +65,10 @@ public static TtlIndexOptions build(final TtlIndexOptions options, final Iterabl
return options.fields(fields);
}

public static ZKDIndexOptions build(final ZKDIndexOptions 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
93 changes: 93 additions & 0 deletions src/main/java/com/arangodb/model/ZKDIndexOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* DISCLAIMER
*
* Copyright 2016 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 Michele Rastelli
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-multi-dim.html">API Documentation</a>
* @since ArangoDB 3.9
*/
public class ZKDIndexOptions extends IndexOptions<ZKDIndexOptions> {

private Iterable<String> fields;
protected final IndexType type = IndexType.zkd;
private Boolean unique;
private FieldValueTypes fieldValueTypes;

public ZKDIndexOptions() {
super();
}

@Override
protected ZKDIndexOptions getThis() {
return this;
}

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

/**
* @param fields A list of attribute paths
* @return options
*/
protected ZKDIndexOptions fields(final Iterable<String> fields) {
this.fields = fields;
return this;
}

protected IndexType getType() {
return type;
}

public Boolean getUnique() {
return unique;
}

/**
* @param unique if true, then create a unique index
* @return options
*/
public ZKDIndexOptions unique(final Boolean unique) {
this.unique = unique;
return this;
}

public FieldValueTypes getFieldValueTypes() {
return fieldValueTypes;
}

/**
* @param fieldValueTypes must be {@link FieldValueTypes#DOUBLE}, currently only doubles are supported as values.
* @return options
*/
public ZKDIndexOptions fieldValueTypes(final FieldValueTypes fieldValueTypes) {
this.fieldValueTypes = fieldValueTypes;
return this;
}

public enum FieldValueTypes {
DOUBLE
}

}
67 changes: 50 additions & 17 deletions src/test/java/com/arangodb/ArangoCollectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,8 @@
import com.arangodb.entity.MultiDocumentEntity;
import com.arangodb.entity.Permissions;
import com.arangodb.entity.ShardEntity;
import com.arangodb.model.CollectionCreateOptions;
import com.arangodb.model.CollectionPropertiesOptions;
import com.arangodb.model.CollectionSchema;
import com.arangodb.model.DocumentCreateOptions;
import com.arangodb.model.DocumentDeleteOptions;
import com.arangodb.model.DocumentExistsOptions;
import com.arangodb.model.DocumentImportOptions;
import com.arangodb.model.*;
import com.arangodb.model.DocumentImportOptions.OnDuplicate;
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.OverwriteMode;
import com.arangodb.model.PersistentIndexOptions;
import com.arangodb.model.SkiplistIndexOptions;
import com.arangodb.model.TtlIndexOptions;
import com.arangodb.util.MapBuilder;
import com.arangodb.velocypack.VPackSlice;
import com.fasterxml.jackson.core.JsonProcessingException;
Expand Down Expand Up @@ -1429,6 +1413,55 @@ public void createPersistentIndexWithOptions() {
assertThat(indexResult.getName(), is(name));
}

@Test
public void createZKDIndex() {
assumeTrue(isAtLeastVersion(3, 9));
collection.truncate();
String f1 = "field-" + rnd();
String f2 = "field-" + rnd();
final Collection<String> fields = Arrays.asList(f1, f2);

final IndexEntity indexResult = collection.ensureZKDIndex(fields, null);
assertThat(indexResult, is(notNullValue()));
assertThat(indexResult.getConstraint(), is(nullValue()));
assertThat(indexResult.getFields(), hasItem(f1));
assertThat(indexResult.getFields(), hasItem(f2));
assertThat(indexResult.getId(), startsWith(COLLECTION_NAME));
assertThat(indexResult.getIsNewlyCreated(), is(true));
assertThat(indexResult.getMinLength(), is(nullValue()));
assertThat(indexResult.getType(), is(IndexType.zkd));
assertThat(indexResult.getUnique(), is(false));
collection.deleteIndex(indexResult.getId());
}

@Test
public void createZKDIndexWithOptions() {
assumeTrue(isAtLeastVersion(3, 9));
collection.truncate();

String name = "ZKDIndex-" + rnd();
final ZKDIndexOptions options = new ZKDIndexOptions()
.name(name)
.fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE);

String f1 = "field-" + rnd();
String f2 = "field-" + rnd();

final Collection<String> fields = Arrays.asList(f1, f2);
final IndexEntity indexResult = collection.ensureZKDIndex(fields, options);
assertThat(indexResult, is(notNullValue()));
assertThat(indexResult.getConstraint(), is(nullValue()));
assertThat(indexResult.getFields(), hasItem(f1));
assertThat(indexResult.getFields(), hasItem(f2));
assertThat(indexResult.getId(), startsWith(COLLECTION_NAME));
assertThat(indexResult.getIsNewlyCreated(), is(true));
assertThat(indexResult.getMinLength(), is(nullValue()));
assertThat(indexResult.getType(), is(IndexType.zkd));
assertThat(indexResult.getUnique(), is(false));
assertThat(indexResult.getName(), is(name));
collection.deleteIndex(indexResult.getId());
}

@Test
public void indexEstimates() {
assumeTrue(isAtLeastVersion(3, 8));
Expand Down
Loading