Skip to content

Commit 0f99d4e

Browse files
authored
[DE-80] zkd indexes (#417)
* zkd indexes * fixed zkd indexes tests * fixed merge issue
1 parent 8c7b665 commit 0f99d4e

13 files changed

+259
-22
lines changed

src/main/java/com/arangodb/ArangoCollection.java

+13
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,19 @@ <T> MultiDocumentEntity<DocumentDeleteEntity<T>> deleteDocuments(
528528
*/
529529
IndexEntity ensureTtlIndex(Iterable<String> fields, TtlIndexOptions options) throws ArangoDBException;
530530

531+
/**
532+
* Creates a ZKD multi-dimensional index for the collection, if it does not already exist.
533+
* Note that zkd indexes are an experimental feature in ArangoDB 3.9.
534+
*
535+
* @param fields A list of attribute paths
536+
* @param options Additional options, can be null
537+
* @return information about the index
538+
* @throws ArangoDBException
539+
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-multi-dim.html">API Documentation</a>
540+
* @since ArangoDB 3.9
541+
*/
542+
IndexEntity ensureZKDIndex(Iterable<String> fields, ZKDIndexOptions options) throws ArangoDBException;
543+
531544
/**
532545
* Fetches a list of all indexes on this collection.
533546
*

src/main/java/com/arangodb/async/ArangoCollectionAsync.java

+16-4
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,10 @@ <T> CompletableFuture<DocumentUpdateEntity<T>> updateDocument(
270270
* to patch (the patch document). All attributes from the patch document will be added to the existing document if
271271
* they do not yet exist, and overwritten in the existing document if they do exist there.
272272
*
273-
* @param key The key of the document
274-
* @param value A representation of a single document (POJO, VPackSlice or String for Json)
275-
* @param options Additional options, can be null
276-
* @param returnType Type of the returned newDocument and/or oldDocument
273+
* @param key The key of the document
274+
* @param value A representation of a single document (POJO, VPackSlice or String for Json)
275+
* @param options Additional options, can be null
276+
* @param returnType Type of the returned newDocument and/or oldDocument
277277
* @return information about the document
278278
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-document">API
279279
* Documentation</a>
@@ -497,6 +497,18 @@ CompletableFuture<IndexEntity> ensureFulltextIndex(
497497
*/
498498
CompletableFuture<IndexEntity> ensureTtlIndex(Iterable<String> fields, TtlIndexOptions options);
499499

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

src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java

+7
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,13 @@ public CompletableFuture<IndexEntity> ensureTtlIndex(Iterable<String> fields, Tt
301301
return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
302302
}
303303

304+
@Override
305+
public CompletableFuture<IndexEntity> ensureZKDIndex(
306+
final Iterable<String> fields,
307+
final ZKDIndexOptions options) {
308+
return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class);
309+
}
310+
304311
@Override
305312
public CompletableFuture<Collection<IndexEntity>> getIndexes() {
306313
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());

src/main/java/com/arangodb/entity/IndexType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@
2525
* @author Heiko Kernbach
2626
*/
2727
public enum IndexType {
28-
primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl
28+
primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl, zkd
2929
}

src/main/java/com/arangodb/internal/ArangoCollectionImpl.java

+6
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ public IndexEntity ensureTtlIndex(final Iterable<String> fields, final TtlIndexO
295295
return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class);
296296
}
297297

298+
@Override
299+
public IndexEntity ensureZKDIndex(final Iterable<String> fields, final ZKDIndexOptions options)
300+
throws ArangoDBException {
301+
return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class);
302+
}
303+
298304
@Override
299305
public Collection<IndexEntity> getIndexes() throws ArangoDBException {
300306
return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer());

src/main/java/com/arangodb/internal/InternalArangoCollection.java

+9
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,15 @@ protected Request createTtlIndexRequest(final Iterable<String> fields, final Ttl
596596
return request;
597597
}
598598

599+
protected Request createZKDIndexRequest(
600+
final Iterable<String> fields, final ZKDIndexOptions options) {
601+
final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX);
602+
request.putQueryParam(COLLECTION, name);
603+
request.setBody(util().serialize(OptionsBuilder.build(options != null ? options :
604+
new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields)));
605+
return request;
606+
}
607+
599608
protected Request getIndexesRequest() {
600609
final Request request = request(db.dbName(), RequestType.GET, PATH_API_INDEX);
601610
request.putQueryParam(COLLECTION, name);

src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java

+5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer;
5757
import com.arangodb.entity.arangosearch.analyzer.TextAnalyzer;
5858
import com.arangodb.model.CollectionSchema;
59+
import com.arangodb.model.ZKDIndexOptions;
5960
import com.arangodb.velocypack.VPackDeserializer;
6061
import com.arangodb.velocypack.VPackParser;
6162
import com.arangodb.velocypack.VPackSlice;
@@ -332,4 +333,8 @@ protected static FieldLink deserializeField(final Entry<String, VPackSlice> fiel
332333
return collectionValidation;
333334
};
334335

336+
public static final VPackDeserializer<ZKDIndexOptions.FieldValueTypes> ZKD_FIELD_VALUE_TYPES =
337+
(parent, vpack, context) -> ZKDIndexOptions.FieldValueTypes.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH));
338+
339+
335340
}

src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest;
3131
import com.arangodb.model.CollectionSchema;
3232
import com.arangodb.model.TraversalOptions;
33+
import com.arangodb.model.ZKDIndexOptions;
3334
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
3435
import com.arangodb.velocypack.VPackModule;
3536
import com.arangodb.velocypack.VPackParserModule;
@@ -70,6 +71,7 @@ public <C extends VPackSetupContext<C>> void setup(final C context) {
7071
context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES);
7172
context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE);
7273
context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION);
74+
context.registerSerializer(ZKDIndexOptions.FieldValueTypes.class, VPackSerializers.ZKD_FIELD_VALUE_TYPES);
7375

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

9497
@Override

src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.arangodb.model.CollectionSchema;
4343
import com.arangodb.model.TraversalOptions;
4444
import com.arangodb.model.TraversalOptions.Order;
45+
import com.arangodb.model.ZKDIndexOptions;
4546
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
4647
import com.arangodb.velocypack.VPackBuilder;
4748
import com.arangodb.velocypack.VPackParser;
@@ -285,4 +286,7 @@ private static void serializeFieldLinks(final VPackBuilder builder, final Collec
285286
context.serialize(builder, attribute, doc);
286287
};
287288

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

src/main/java/com/arangodb/model/OptionsBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public static TtlIndexOptions build(final TtlIndexOptions options, final Iterabl
6565
return options.fields(fields);
6666
}
6767

68+
public static ZKDIndexOptions build(final ZKDIndexOptions options, final Iterable<String> fields) {
69+
return options.fields(fields);
70+
}
71+
6872
public static CollectionCreateOptions build(final CollectionCreateOptions options, final String name) {
6973
return options.name(name);
7074
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* DISCLAIMER
3+
*
4+
* Copyright 2016 ArangoDB GmbH, Cologne, Germany
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
*/
20+
21+
package com.arangodb.model;
22+
23+
import com.arangodb.entity.IndexType;
24+
25+
/**
26+
* @author Michele Rastelli
27+
* @see <a href="https://www.arangodb.com/docs/stable/http/indexes-multi-dim.html">API Documentation</a>
28+
* @since ArangoDB 3.9
29+
*/
30+
public class ZKDIndexOptions extends IndexOptions<ZKDIndexOptions> {
31+
32+
private Iterable<String> fields;
33+
protected final IndexType type = IndexType.zkd;
34+
private Boolean unique;
35+
private FieldValueTypes fieldValueTypes;
36+
37+
public ZKDIndexOptions() {
38+
super();
39+
}
40+
41+
@Override
42+
protected ZKDIndexOptions getThis() {
43+
return this;
44+
}
45+
46+
protected Iterable<String> getFields() {
47+
return fields;
48+
}
49+
50+
/**
51+
* @param fields A list of attribute paths
52+
* @return options
53+
*/
54+
protected ZKDIndexOptions fields(final Iterable<String> fields) {
55+
this.fields = fields;
56+
return this;
57+
}
58+
59+
protected IndexType getType() {
60+
return type;
61+
}
62+
63+
public Boolean getUnique() {
64+
return unique;
65+
}
66+
67+
/**
68+
* @param unique if true, then create a unique index
69+
* @return options
70+
*/
71+
public ZKDIndexOptions unique(final Boolean unique) {
72+
this.unique = unique;
73+
return this;
74+
}
75+
76+
public FieldValueTypes getFieldValueTypes() {
77+
return fieldValueTypes;
78+
}
79+
80+
/**
81+
* @param fieldValueTypes must be {@link FieldValueTypes#DOUBLE}, currently only doubles are supported as values.
82+
* @return options
83+
*/
84+
public ZKDIndexOptions fieldValueTypes(final FieldValueTypes fieldValueTypes) {
85+
this.fieldValueTypes = fieldValueTypes;
86+
return this;
87+
}
88+
89+
public enum FieldValueTypes {
90+
DOUBLE
91+
}
92+
93+
}

src/test/java/com/arangodb/ArangoCollectionTest.java

+50-17
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,8 @@
3535
import com.arangodb.entity.MultiDocumentEntity;
3636
import com.arangodb.entity.Permissions;
3737
import com.arangodb.entity.ShardEntity;
38-
import com.arangodb.model.CollectionCreateOptions;
39-
import com.arangodb.model.CollectionPropertiesOptions;
40-
import com.arangodb.model.CollectionSchema;
41-
import com.arangodb.model.DocumentCreateOptions;
42-
import com.arangodb.model.DocumentDeleteOptions;
43-
import com.arangodb.model.DocumentExistsOptions;
44-
import com.arangodb.model.DocumentImportOptions;
38+
import com.arangodb.model.*;
4539
import com.arangodb.model.DocumentImportOptions.OnDuplicate;
46-
import com.arangodb.model.DocumentReadOptions;
47-
import com.arangodb.model.DocumentReplaceOptions;
48-
import com.arangodb.model.DocumentUpdateOptions;
49-
import com.arangodb.model.FulltextIndexOptions;
50-
import com.arangodb.model.GeoIndexOptions;
51-
import com.arangodb.model.HashIndexOptions;
52-
import com.arangodb.model.OverwriteMode;
53-
import com.arangodb.model.PersistentIndexOptions;
54-
import com.arangodb.model.SkiplistIndexOptions;
55-
import com.arangodb.model.TtlIndexOptions;
5640
import com.arangodb.util.MapBuilder;
5741
import com.arangodb.velocypack.VPackSlice;
5842
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -1429,6 +1413,55 @@ public void createPersistentIndexWithOptions() {
14291413
assertThat(indexResult.getName(), is(name));
14301414
}
14311415

1416+
@Test
1417+
public void createZKDIndex() {
1418+
assumeTrue(isAtLeastVersion(3, 9));
1419+
collection.truncate();
1420+
String f1 = "field-" + rnd();
1421+
String f2 = "field-" + rnd();
1422+
final Collection<String> fields = Arrays.asList(f1, f2);
1423+
1424+
final IndexEntity indexResult = collection.ensureZKDIndex(fields, null);
1425+
assertThat(indexResult, is(notNullValue()));
1426+
assertThat(indexResult.getConstraint(), is(nullValue()));
1427+
assertThat(indexResult.getFields(), hasItem(f1));
1428+
assertThat(indexResult.getFields(), hasItem(f2));
1429+
assertThat(indexResult.getId(), startsWith(COLLECTION_NAME));
1430+
assertThat(indexResult.getIsNewlyCreated(), is(true));
1431+
assertThat(indexResult.getMinLength(), is(nullValue()));
1432+
assertThat(indexResult.getType(), is(IndexType.zkd));
1433+
assertThat(indexResult.getUnique(), is(false));
1434+
collection.deleteIndex(indexResult.getId());
1435+
}
1436+
1437+
@Test
1438+
public void createZKDIndexWithOptions() {
1439+
assumeTrue(isAtLeastVersion(3, 9));
1440+
collection.truncate();
1441+
1442+
String name = "ZKDIndex-" + rnd();
1443+
final ZKDIndexOptions options = new ZKDIndexOptions()
1444+
.name(name)
1445+
.fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE);
1446+
1447+
String f1 = "field-" + rnd();
1448+
String f2 = "field-" + rnd();
1449+
1450+
final Collection<String> fields = Arrays.asList(f1, f2);
1451+
final IndexEntity indexResult = collection.ensureZKDIndex(fields, options);
1452+
assertThat(indexResult, is(notNullValue()));
1453+
assertThat(indexResult.getConstraint(), is(nullValue()));
1454+
assertThat(indexResult.getFields(), hasItem(f1));
1455+
assertThat(indexResult.getFields(), hasItem(f2));
1456+
assertThat(indexResult.getId(), startsWith(COLLECTION_NAME));
1457+
assertThat(indexResult.getIsNewlyCreated(), is(true));
1458+
assertThat(indexResult.getMinLength(), is(nullValue()));
1459+
assertThat(indexResult.getType(), is(IndexType.zkd));
1460+
assertThat(indexResult.getUnique(), is(false));
1461+
assertThat(indexResult.getName(), is(name));
1462+
collection.deleteIndex(indexResult.getId());
1463+
}
1464+
14321465
@Test
14331466
public void indexEstimates() {
14341467
assumeTrue(isAtLeastVersion(3, 8));

0 commit comments

Comments
 (0)