diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java index 95b830fef..e2c5e8db6 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java @@ -26,18 +26,30 @@ /** * @author Mark Vollmary + * @author Heiko Kernbach * */ public class ArangoSearchProperties { private Long consolidationIntervalMsec; + private Long commitIntervalMsec; private Long cleanupIntervalStep; private ConsolidationPolicy consolidationPolicy; + private final Collection primarySorts; private final Collection links; public ArangoSearchProperties() { super(); links = new ArrayList(); + primarySorts = new ArrayList(); + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public void setCommitIntervalMsec(final Long commitIntervalMsec) { + this.commitIntervalMsec = commitIntervalMsec; } public Long getConsolidationIntervalMsec() { @@ -72,4 +84,11 @@ public void addLink(final CollectionLink... links) { this.links.addAll(Arrays.asList(links)); } + public Collection getPrimarySort() { + return primarySorts; + } + + public void addPrimarySort(final PrimarySort... primarySorts) { + this.primarySorts.addAll(Arrays.asList(primarySorts)); + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index a4fe5ddfa..dd8b9f634 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -27,49 +27,71 @@ /** * @author Mark Vollmary - * */ public class ArangoSearchPropertiesEntity extends ViewEntity { - private final ArangoSearchProperties properties; + private final ArangoSearchProperties properties; + + public ArangoSearchPropertiesEntity(final String id, final String name, final ViewType type, + final ArangoSearchProperties properties) { + super(id, name, type); + this.properties = properties; + } - public ArangoSearchPropertiesEntity(final String id, final String name, final ViewType type, - final ArangoSearchProperties properties) { - super(id, name, type); - this.properties = properties; - } + /** + * @return Wait at least this many milliseconds between committing index data changes and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and memory usage would continue + * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and + * waste disk space for each commit call without any added benefits. + */ + public Long getConsolidationIntervalMsec() { + return properties.getConsolidationIntervalMsec(); + } - /** - * @return Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would continue - * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and - * waste disk space for each commit call without any added benefits. - */ - public Long getConsolidationIntervalMsec() { - return properties.getConsolidationIntervalMsec(); - } + /** + * @return Wait at least this many milliseconds between committing view data store changes and making documents + * visible to queries (default: 1000, to disable use: 0). For the case where there are a lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and memory usage would continue to grow. + * For the case where there are a few inserts/updates, a higher value will impact performance and waste disk space + * for each commit call without any added benefits. Background: For data retrieval ArangoSearch views follow the + * concept of “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by corresponding + * query expressions. The concept of ArangoSearch view “commit” operation is introduced to control the upper-bound + * on the time until document addition/removals are actually reflected by corresponding query expressions. Once a + * “commit” operation is complete all documents added/removed prior to the start of the “commit” operation will be + * reflected by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will still + * continue to return a repeatable-read state. + */ + public Long getCommitIntervalMsec() { + return properties.getCommitIntervalMsec(); + } - /** - * @return Wait at least this many commits between removing unused files in data directory (default: 10, to disable - * use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of - * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the - * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact - * performance without any added benefits. - */ - public Long getCleanupIntervalStep() { - return properties.getCleanupIntervalStep(); - } + /** + * @return Wait at least this many commits between removing unused files in data directory (default: 10, to disable + * use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of + * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the + * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * performance without any added benefits. + */ + public Long getCleanupIntervalStep() { + return properties.getCleanupIntervalStep(); + } - public ConsolidationPolicy getConsolidationPolicy() { - return properties.getConsolidationPolicy(); - } + public ConsolidationPolicy getConsolidationPolicy() { + return properties.getConsolidationPolicy(); + } - /** - * @return A list of linked collections - */ - public Collection getLinks() { - return properties.getLinks(); - } + /** + * @return A list of linked collections + */ + public Collection getLinks() { + return properties.getLinks(); + } + /** + * @return A list of primary sort objects + */ + public Collection getPrimarySort() { + return properties.getPrimarySort(); + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java new file mode 100644 index 000000000..74884404f --- /dev/null +++ b/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java @@ -0,0 +1,61 @@ +/* + * 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.entity.arangosearch; + +/** + * @author Heiko Kernbach + * + */ +public class PrimarySort { + + private final String fieldName; + private Boolean ascending; + + private PrimarySort(final String fieldName) { + super(); + this.fieldName = fieldName; + } + + public static PrimarySort on(final String fieldName) { + return new PrimarySort(fieldName); + } + + /** + * @param ascending + * @return primarySort + */ + public PrimarySort ascending(final Boolean ascending) { + if (ascending) { + this.ascending = true; + } else { + this.ascending = false; + } + return this; + } + + public Boolean getAscending() { + return ascending; + } + + public String getFieldName() { + return fieldName; + } +} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index fde352d8b..6278e1453 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -28,16 +28,10 @@ import java.util.Map.Entry; import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.StoreValuesType; import com.arangodb.velocypack.VPackDeserializationContext; import com.arangodb.velocypack.VPackDeserializer; import com.arangodb.velocypack.VPackSlice; @@ -223,10 +217,17 @@ public ArangoSearchProperties deserialize( if (consolidationIntervalMsec.isInteger()) { properties.setConsolidationIntervalMsec(consolidationIntervalMsec.getAsLong()); } + + final VPackSlice commitIntervalMsec = vpack.get("commitIntervalMsec"); + if (commitIntervalMsec.isInteger()) { + properties.setCommitIntervalMsec(commitIntervalMsec.getAsLong()); + } + final VPackSlice cleanupIntervalStep = vpack.get("cleanupIntervalStep"); if (cleanupIntervalStep.isInteger()) { properties.setCleanupIntervalStep(cleanupIntervalStep.getAsLong()); } + final VPackSlice consolidationPolicy = vpack.get("consolidationPolicy"); if (consolidationPolicy.isObject()) { properties.setConsolidationPolicy( @@ -269,6 +270,22 @@ public ArangoSearchProperties deserialize( properties.addLink(link); } } + + final VPackSlice primarySorts = vpack.get("primarySort"); + if (primarySorts.isArray()) { + final Iterator primarySortsIterator = primarySorts.arrayIterator(); + for (; primarySortsIterator.hasNext();) { + final VPackSlice entry = primarySortsIterator.next(); + if (entry.isObject()) { + if (entry.get("field").isString() && entry.get("asc").isBoolean()) { + final PrimarySort primarySort = PrimarySort.on(entry.get("field").getAsString()); + primarySort.ascending(entry.get("asc").getAsBoolean()); + properties.addPrimarySort(primarySort); + } + } + } + } + return properties; } }; diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index 95b2d9088..54154e7aa 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -26,11 +26,7 @@ import java.util.Map.Entry; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.StoreValuesType; +import com.arangodb.entity.arangosearch.*; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.model.TraversalOptions; import com.arangodb.model.TraversalOptions.Order; @@ -44,281 +40,298 @@ /** * @author Mark Vollmary - * */ public class VPackSerializers { - public static final VPackSerializer REQUEST = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final Request value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getDatabase()); - builder.add(value.getRequestType().getType()); - builder.add(value.getRequest()); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getQueryParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getHeaderParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.close(); - } - }; + public static final VPackSerializer REQUEST = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final Request value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, ValueType.ARRAY); + builder.add(value.getVersion()); + builder.add(value.getType()); + builder.add(value.getDatabase()); + builder.add(value.getRequestType().getType()); + builder.add(value.getRequest()); + builder.add(ValueType.OBJECT); + for (final Entry entry : value.getQueryParam().entrySet()) { + builder.add(entry.getKey(), entry.getValue()); + } + builder.close(); + builder.add(ValueType.OBJECT); + for (final Entry entry : value.getHeaderParam().entrySet()) { + builder.add(entry.getKey(), entry.getValue()); + } + builder.close(); + builder.close(); + } + }; + + public static final VPackSerializer AUTH_REQUEST = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final AuthenticationRequest value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, ValueType.ARRAY); + builder.add(value.getVersion()); + builder.add(value.getType()); + builder.add(value.getEncryption()); + builder.add(value.getUser()); + builder.add(value.getPassword()); + builder.close(); + } + }; + + public static final VPackSerializer COLLECTION_TYPE = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final CollectionType value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, value.getType()); + } + }; + + public static final VPackSerializer BASE_DOCUMENT = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final BaseDocument value, + final VPackSerializationContext context) throws VPackException { + final Map doc = new HashMap(); + doc.putAll(value.getProperties()); + doc.put(DocumentField.Type.ID.getSerializeName(), value.getId()); + doc.put(DocumentField.Type.KEY.getSerializeName(), value.getKey()); + doc.put(DocumentField.Type.REV.getSerializeName(), value.getRevision()); + context.serialize(builder, attribute, doc); + } + }; - public static final VPackSerializer AUTH_REQUEST = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final AuthenticationRequest value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getEncryption()); - builder.add(value.getUser()); - builder.add(value.getPassword()); - builder.close(); - } - }; + public static final VPackSerializer BASE_EDGE_DOCUMENT = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final BaseEdgeDocument value, + final VPackSerializationContext context) throws VPackException { + final Map doc = new HashMap(); + doc.putAll(value.getProperties()); + doc.put(DocumentField.Type.ID.getSerializeName(), value.getId()); + doc.put(DocumentField.Type.KEY.getSerializeName(), value.getKey()); + doc.put(DocumentField.Type.REV.getSerializeName(), value.getRevision()); + doc.put(DocumentField.Type.FROM.getSerializeName(), value.getFrom()); + doc.put(DocumentField.Type.TO.getSerializeName(), value.getTo()); + context.serialize(builder, attribute, doc); + } + }; - public static final VPackSerializer COLLECTION_TYPE = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final CollectionType value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, value.getType()); - } - }; + public static final VPackSerializer TRAVERSAL_ORDER = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final Order value, + final VPackSerializationContext context) throws VPackException { + if (TraversalOptions.Order.preorder_expander == value) { + builder.add(attribute, "preorder-expander"); + } else { + builder.add(attribute, value.name()); + } + } + }; - public static final VPackSerializer BASE_DOCUMENT = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final BaseDocument value, - final VPackSerializationContext context) throws VPackException { - final Map doc = new HashMap(); - doc.putAll(value.getProperties()); - doc.put(DocumentField.Type.ID.getSerializeName(), value.getId()); - doc.put(DocumentField.Type.KEY.getSerializeName(), value.getKey()); - doc.put(DocumentField.Type.REV.getSerializeName(), value.getRevision()); - context.serialize(builder, attribute, doc); - } - }; + public static final VPackSerializer LOG_LEVEL = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final LogLevel value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, value.getLevel()); + } + }; - public static final VPackSerializer BASE_EDGE_DOCUMENT = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final BaseEdgeDocument value, - final VPackSerializationContext context) throws VPackException { - final Map doc = new HashMap(); - doc.putAll(value.getProperties()); - doc.put(DocumentField.Type.ID.getSerializeName(), value.getId()); - doc.put(DocumentField.Type.KEY.getSerializeName(), value.getKey()); - doc.put(DocumentField.Type.REV.getSerializeName(), value.getRevision()); - doc.put(DocumentField.Type.FROM.getSerializeName(), value.getFrom()); - doc.put(DocumentField.Type.TO.getSerializeName(), value.getTo()); - context.serialize(builder, attribute, doc); - } - }; + public static final VPackSerializer PERMISSIONS = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final Permissions value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, value.toString().toLowerCase()); + } + }; - public static final VPackSerializer TRAVERSAL_ORDER = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final Order value, - final VPackSerializationContext context) throws VPackException { - if (TraversalOptions.Order.preorder_expander == value) { - builder.add(attribute, "preorder-expander"); - } else { - builder.add(attribute, value.name()); - } - } - }; + public static final VPackSerializer REPLICATION_FACTOR = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final ReplicationFactor value, + final VPackSerializationContext context) throws VPackException { + final Boolean satellite = value.getSatellite(); + if (Boolean.TRUE == satellite) { + builder.add(attribute, "satellite"); + } else if (value.getReplicationFactor() != null) { + builder.add(attribute, value.getReplicationFactor()); + } + } + }; - public static final VPackSerializer LOG_LEVEL = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final LogLevel value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, value.getLevel()); - } - }; + public static final VPackSerializer MIN_REPLICATION_FACTOR = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final MinReplicationFactor value, + final VPackSerializationContext context) throws VPackException { + if (value.getMinReplicationFactor() != null) { + builder.add(attribute, value.getMinReplicationFactor()); + } + } + }; - public static final VPackSerializer PERMISSIONS = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final Permissions value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, value.toString().toLowerCase()); - } - }; + public static final VPackSerializer VIEW_TYPE = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final ViewType value, + final VPackSerializationContext context) throws VPackException { + final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(); + builder.add(attribute, type); + } + }; - public static final VPackSerializer REPLICATION_FACTOR = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final ReplicationFactor value, - final VPackSerializationContext context) throws VPackException { - final Boolean satellite = value.getSatellite(); - if (Boolean.TRUE == satellite) { - builder.add(attribute, "satellite"); - } else if (value.getReplicationFactor() != null) { - builder.add(attribute, value.getReplicationFactor()); - } - } - }; + public static final VPackSerializer ARANGO_SEARCH_PROPERTIES_OPTIONS = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final ArangoSearchPropertiesOptions value, + final VPackSerializationContext context) throws VPackException { + builder.add(ValueType.OBJECT); + context.serialize(builder, attribute, value.getProperties()); + builder.close(); + } + }; - public static final VPackSerializer MIN_REPLICATION_FACTOR = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final MinReplicationFactor value, - final VPackSerializationContext context) throws VPackException { - if (value.getMinReplicationFactor() != null) { - builder.add(attribute, value.getMinReplicationFactor()); - } - } - }; + public static final VPackSerializer ARANGO_SEARCH_PROPERTIES = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final ArangoSearchProperties value, + final VPackSerializationContext context) throws VPackException { + final Long consolidationIntervalMsec = value.getConsolidationIntervalMsec(); + if (consolidationIntervalMsec != null) { + builder.add("consolidationIntervalMsec", consolidationIntervalMsec); + } - public static final VPackSerializer VIEW_TYPE = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final ViewType value, - final VPackSerializationContext context) throws VPackException { - final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(); - builder.add(attribute, type); - } - }; + final Long commitIntervalMsec = value.getCommitIntervalMsec(); + if (commitIntervalMsec != null) { + builder.add("commitIntervalMsec", commitIntervalMsec); + } - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES_OPTIONS = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final ArangoSearchPropertiesOptions value, - final VPackSerializationContext context) throws VPackException { - builder.add(ValueType.OBJECT); - context.serialize(builder, attribute, value.getProperties()); - builder.close(); - } - }; + final Long cleanupIntervalStep = value.getCleanupIntervalStep(); + if (cleanupIntervalStep != null) { + builder.add("cleanupIntervalStep", cleanupIntervalStep); + } + context.serialize(builder, "consolidationPolicy", value.getConsolidationPolicy()); - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final ArangoSearchProperties value, - final VPackSerializationContext context) throws VPackException { - final Long consolidationIntervalMsec = value.getConsolidationIntervalMsec(); - if (consolidationIntervalMsec != null) { - builder.add("consolidationIntervalMsec", consolidationIntervalMsec); - } - final Long cleanupIntervalStep = value.getCleanupIntervalStep(); - if (cleanupIntervalStep != null) { - builder.add("cleanupIntervalStep", cleanupIntervalStep); - } - context.serialize(builder, "consolidationPolicy", value.getConsolidationPolicy()); + final Collection links = value.getLinks(); + if (!links.isEmpty()) { + builder.add("links", ValueType.OBJECT); + for (final CollectionLink collectionLink : links) { + builder.add(collectionLink.getName(), ValueType.OBJECT); + final Collection analyzers = collectionLink.getAnalyzers(); + if (!analyzers.isEmpty()) { + builder.add("analyzers", ValueType.ARRAY); + for (final String analyzer : analyzers) { + builder.add(analyzer); + } + builder.close(); + } + final Boolean includeAllFields = collectionLink.getIncludeAllFields(); + if (includeAllFields != null) { + builder.add("includeAllFields", includeAllFields); + } + final Boolean trackListPositions = collectionLink.getTrackListPositions(); + if (trackListPositions != null) { + builder.add("trackListPositions", trackListPositions); + } + final StoreValuesType storeValues = collectionLink.getStoreValues(); + if (storeValues != null) { + builder.add("storeValues", storeValues.name().toLowerCase()); + } + serializeFieldLinks(builder, collectionLink.getFields()); + builder.close(); + } + builder.close(); + } - final Collection links = value.getLinks(); - if (!links.isEmpty()) { - builder.add("links", ValueType.OBJECT); - for (final CollectionLink collectionLink : links) { - builder.add(collectionLink.getName(), ValueType.OBJECT); - final Collection analyzers = collectionLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = collectionLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = collectionLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = collectionLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase()); - } - serializeFieldLinks(builder, collectionLink.getFields()); - builder.close(); - } - builder.close(); - } - } - }; + final Collection primarySorts = value.getPrimarySort(); + if (!primarySorts.isEmpty()) { + builder.add("primarySort", ValueType.ARRAY); // open array + for (final PrimarySort primarySort : primarySorts) { + builder.add(ValueType.OBJECT); // open object + builder.add("field", primarySort.getFieldName()); + builder.add("asc", primarySort.getAscending()); + builder.close(); // close object + } + builder.close(); // close array + } + } + }; - private static void serializeFieldLinks(final VPackBuilder builder, final Collection links) { - if (!links.isEmpty()) { - builder.add("fields", ValueType.OBJECT); - for (final FieldLink fieldLink : links) { - builder.add(fieldLink.getName(), ValueType.OBJECT); - final Collection analyzers = fieldLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = fieldLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = fieldLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = fieldLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase()); - } - serializeFieldLinks(builder, fieldLink.getFields()); - builder.close(); - } - builder.close(); - } - } + private static void serializeFieldLinks(final VPackBuilder builder, final Collection links) { + if (!links.isEmpty()) { + builder.add("fields", ValueType.OBJECT); + for (final FieldLink fieldLink : links) { + builder.add(fieldLink.getName(), ValueType.OBJECT); + final Collection analyzers = fieldLink.getAnalyzers(); + if (!analyzers.isEmpty()) { + builder.add("analyzers", ValueType.ARRAY); + for (final String analyzer : analyzers) { + builder.add(analyzer); + } + builder.close(); + } + final Boolean includeAllFields = fieldLink.getIncludeAllFields(); + if (includeAllFields != null) { + builder.add("includeAllFields", includeAllFields); + } + final Boolean trackListPositions = fieldLink.getTrackListPositions(); + if (trackListPositions != null) { + builder.add("trackListPositions", trackListPositions); + } + final StoreValuesType storeValues = fieldLink.getStoreValues(); + if (storeValues != null) { + builder.add("storeValues", storeValues.name().toLowerCase()); + } + serializeFieldLinks(builder, fieldLink.getFields()); + builder.close(); + } + builder.close(); + } + } - public static final VPackSerializer CONSOLIDATE_TYPE = new VPackSerializer() { - @Override - public void serialize( - final VPackBuilder builder, - final String attribute, - final ConsolidationType value, - final VPackSerializationContext context) throws VPackException { - builder.add(attribute, value.toString().toLowerCase()); - } - }; + public static final VPackSerializer CONSOLIDATE_TYPE = new VPackSerializer() { + @Override + public void serialize( + final VPackBuilder builder, + final String attribute, + final ConsolidationType value, + final VPackSerializationContext context) throws VPackException { + builder.add(attribute, value.toString().toLowerCase()); + } + }; } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index ec08bba80..627f653a4 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -24,6 +24,7 @@ import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.PrimarySort; /** * @author Mark Vollmary @@ -62,6 +63,28 @@ public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidat return this; } + /** + * @param commitIntervalMsec + * + * Wait at least this many milliseconds between committing view data store changes and making documents visible to + * queries (default: 1000, to disable use: 0). For the case where there are a lot of inserts/updates, a lower value, + * until commit, will cause the index not to account for them and memory usage would continue to grow. For the case + * where there are a few inserts/updates, a higher value will impact performance and waste disk space for each + * commit call without any added benefits. Background: For data retrieval ArangoSearch views follow the concept of + * “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by corresponding query + * expressions. The concept of ArangoSearch view “commit” operation is introduced to control the upper-bound on the + * time until document addition/removals are actually reflected by corresponding query expressions. Once a “commit” + * operation is complete all documents added/removed prior to the start of the “commit” operation will be reflected + * by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will still continue to + * return a repeatable-read state. + * + * @return options + */ + public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMsec) { + properties.setCommitIntervalMsec(commitIntervalMsec); + return this; + } + /** * @param cleanupIntervalStep * Wait at least this many commits between removing unused files in data directory (default: 10, to @@ -95,4 +118,14 @@ public ArangoSearchCreateOptions link(final CollectionLink... links) { properties.addLink(links); return this; } + + /** + * @param primarySorts + * A list of linked collections + * @return options + */ + public ArangoSearchCreateOptions primarySort(final PrimarySort... primarySorts) { + properties.addPrimarySort(primarySorts); + return this; + } } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index e340b394c..eb73b942e 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -23,6 +23,7 @@ import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.PrimarySort; /** * @author Mark Vollmary @@ -89,4 +90,14 @@ public ArangoSearchPropertiesOptions link(final CollectionLink... links) { return this; } + /** + * @param primarySorts + * A list of primarySort objects + * @return options + */ + public ArangoSearchPropertiesOptions primarySort(final PrimarySort... primarySorts) { + properties.addPrimarySort(primarySorts); + return this; + } + } diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index 2c57f343b..bc2389bc8 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -27,6 +27,7 @@ import java.util.Collection; +import com.arangodb.entity.arangosearch.*; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -38,12 +39,6 @@ import com.arangodb.entity.ServerRole; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.StoreValuesType; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; @@ -155,6 +150,47 @@ public void createWithOptions() { assertThat(db.arangoSearch(VIEW_NAME).exists(), is(true)); } + @Test + public void createWithPrimarySort() { + if (!requireVersion(3, 5)) { + return; + } + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + + final PrimarySort primarySort = PrimarySort.on("myFieldName"); + primarySort.ascending(true); + options.primarySort(primarySort); + options.consolidationIntervalMsec(666666L); + + final ViewEntity info = db.arangoSearch(VIEW_NAME).create(options); + assertThat(info, is(not(nullValue()))); + assertThat(info.getId(), is(not(nullValue()))); + assertThat(info.getName(), is(VIEW_NAME)); + assertThat(info.getType(), is(ViewType.ARANGO_SEARCH)); + assertThat(db.arangoSearch(VIEW_NAME).exists(), is(true)); + } + + @Test + public void createWithCommitIntervalMsec() { + if (!requireVersion(3, 5)) { + return; + } + final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); + options.commitIntervalMsec(666666L); + + final ViewEntity info = db.arangoSearch(VIEW_NAME).create(options); + assertThat(info, is(not(nullValue()))); + assertThat(info.getId(), is(not(nullValue()))); + assertThat(info.getName(), is(VIEW_NAME)); + assertThat(info.getType(), is(ViewType.ARANGO_SEARCH)); + assertThat(db.arangoSearch(VIEW_NAME).exists(), is(true)); + + // check commit interval msec property + final ArangoSearch view = db.arangoSearch(VIEW_NAME); + final ArangoSearchPropertiesEntity properties = view.getProperties(); + assertThat(properties.getCommitIntervalMsec(), is(666666L)); + } + @Test public void getProperties() { if (!requireVersion(3, 4)) {