blob: 015f3e2772c9c319e20038567b766ee1e015060d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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.
*/
package org.apache.hugegraph.core;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hugegraph.HugeException;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.BackendException;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.Id.IdType;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.backend.id.SnowflakeIdGenerator;
import org.apache.hugegraph.backend.id.SplicingIdGenerator;
import org.apache.hugegraph.backend.page.PageInfo;
import org.apache.hugegraph.backend.query.Condition;
import org.apache.hugegraph.backend.query.ConditionQuery;
import org.apache.hugegraph.backend.query.Query;
import org.apache.hugegraph.backend.store.BackendTable;
import org.apache.hugegraph.backend.store.Shard;
import org.apache.hugegraph.backend.tx.GraphTransaction;
import org.apache.hugegraph.exception.LimitExceedException;
import org.apache.hugegraph.exception.NoIndexException;
import org.apache.hugegraph.exception.NotAllowException;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.schema.Userdata;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.structure.HugeElement;
import org.apache.hugegraph.testutil.Assert;
import org.apache.hugegraph.testutil.FakeObjects;
import org.apache.hugegraph.testutil.Utils;
import org.apache.hugegraph.testutil.Whitebox;
import org.apache.hugegraph.traversal.optimize.ConditionP;
import org.apache.hugegraph.traversal.optimize.Text;
import org.apache.hugegraph.traversal.optimize.TraversalUtil;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.GraphReadMode;
import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.type.define.WriteType;
import org.apache.hugegraph.util.Blob;
import org.apache.hugegraph.util.CollectionUtil;
import org.apache.hugegraph.util.LongEncoding;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class VertexCoreTest extends BaseCoreTest {
@Before
public void initSchema() {
SchemaManager schema = graph().schema();
LOG.debug("=============== propertyKey ================");
schema.propertyKey("id").asInt().create();
schema.propertyKey("name").asText().create();
schema.propertyKey("dynamic").asBoolean().create();
schema.propertyKey("time").asText().create();
schema.propertyKey("age").asInt().valueSingle().create();
schema.propertyKey("comment").asText().valueList().create();
schema.propertyKey("contribution").asText().valueSet().create();
schema.propertyKey("lived").asText().create();
schema.propertyKey("description").asText().create();
schema.propertyKey("city").asText().create();
schema.propertyKey("cpu").asText().create();
schema.propertyKey("ram").asText().create();
schema.propertyKey("band").asText().create();
schema.propertyKey("price").asInt().create();
schema.propertyKey("weight").asDouble().create();
schema.propertyKey("birth").asDate().create();
LOG.debug("=============== vertexLabel ================");
schema.vertexLabel("person")
.properties("name", "age", "city", "birth")
.primaryKeys("name")
.nullableKeys("age", "birth")
.create();
schema.vertexLabel("computer")
.properties("name", "band", "cpu", "ram", "price")
.primaryKeys("name", "band")
.nullableKeys("ram", "cpu", "price")
.ifNotExist()
.create();
schema.vertexLabel("author")
.properties("id", "name", "age", "lived")
.primaryKeys("id")
.nullableKeys("age", "lived")
.create();
schema.vertexLabel("language")
.properties("name", "dynamic")
.primaryKeys("name")
.nullableKeys("dynamic")
.create();
schema.vertexLabel("book")
.properties("name", "price")
.primaryKeys("name")
.nullableKeys("price")
.create();
schema.vertexLabel("review")
.properties("id", "comment", "contribution")
.primaryKeys("id")
.nullableKeys("comment", "contribution")
.create();
schema.vertexLabel("fan")
.properties("name", "age", "city")
.primaryKeys("name")
.ttl(3000L)
.ifNotExist()
.create();
schema.vertexLabel("follower")
.properties("name", "age", "city", "birth")
.primaryKeys("name")
.ttl(3000L)
.ttlStartTime("birth")
.ifNotExist()
.create();
}
protected void initPersonIndex(boolean indexCity) {
SchemaManager schema = graph().schema();
LOG.debug("=============== person index ================");
schema.indexLabel("personByAge").onV("person").range()
.by("age").create();
schema.indexLabel("personByBirth").onV("person").range()
.by("birth").create();
if (indexCity) {
schema.indexLabel("personByCity").onV("person").secondary()
.by("city").create();
}
}
protected void initComputerIndex() {
SchemaManager schema = graph().schema();
LOG.debug("=============== computer index ================");
schema.indexLabel("pcByBand").onV("computer")
.secondary().by("band")
.ifNotExist()
.create();
schema.indexLabel("pcByCpuAndRamAndBand").onV("computer")
.secondary().by("cpu", "ram", "band")
.ifNotExist()
.create();
}
@Test
public void testAddVertex() {
HugeGraph graph = graph();
// Directly save into the backend
graph.addVertex(T.label, "book", "name", "java-3");
graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
graph.addVertex(T.label, "person", "name", "James",
"city", "Beijing", "age", 19);
graph.addVertex(T.label, "person", "name", "Tom Cat",
"city", "Beijing", "age", 20);
graph.addVertex(T.label, "person", "name", "Lisa",
"city", "Beijing", "age", 20);
graph.addVertex(T.label, "person", "name", "Hebe",
"city", "Taipei", "age", 21);
this.commitTx();
long count = graph.traversal().V().count().next();
Assert.assertEquals(6, count);
}
@Test
public void testAddVertexWithInvalidPropertyType() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "book", "name", 18);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", "should-be-int");
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 18.0);
});
}
@Test
public void testAddVertexWithInvalidPropertyValueOfInt() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("int").asInt().create();
schema.vertexLabel("number").properties("int").create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
long value = Integer.MAX_VALUE + 1L;
graph.addVertex(T.label, "number", "int", value);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
long value = Integer.MIN_VALUE - 1L;
graph.addVertex(T.label, "number", "int", value);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "number", "int", Long.MAX_VALUE);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "number", "int", Long.MIN_VALUE);
});
}
@Test
public void testAddVertexWithInvalidPropertyValueOfLong() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("long").asLong().create();
schema.vertexLabel("number").properties("long").create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
BigDecimal one = new BigDecimal(1);
BigDecimal value = new BigDecimal(Long.MAX_VALUE).add(one);
graph.addVertex(T.label, "number", "long", value);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
BigDecimal one = new BigDecimal(-1);
BigDecimal value = new BigDecimal(Long.MIN_VALUE).add(one);
graph.addVertex(T.label, "number", "long", value);
});
}
@Test
public void testAddVertexWithInvalidPropertyValueOfFloat() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("float").asFloat().create();
schema.vertexLabel("number").properties("float").create();
double value = Float.MIN_VALUE / 2.0d;
float fvalue = graph.addVertex(T.label, "number", "float", value)
.value("float");
Assert.assertEquals(0.0f, fvalue, 0.0d);
fvalue = graph.addVertex(T.label, "number", "float", -value)
.value("float");
Assert.assertEquals(0.0f, fvalue, 0.0d);
fvalue = graph.addVertex(T.label, "number", "float", Double.MIN_VALUE)
.value("float");
Assert.assertEquals(0.0f, fvalue, 0.0d);
}
@Test
public void testAddVertexWithInvalidPropertyValueOfDouble() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("double").asDouble().create();
schema.vertexLabel("number").properties("double").create();
BigDecimal two = new BigDecimal(2);
BigDecimal value = new BigDecimal(Double.MIN_VALUE).divide(two);
double dvalue = graph.addVertex(T.label, "number", "double", value)
.value("double");
Assert.assertEquals(0.0d, dvalue, 0.0d);
value = new BigDecimal(-Double.MIN_VALUE).divide(two);
dvalue = graph.addVertex(T.label, "number", "double", value)
.value("double");
Assert.assertEquals(0.0d, dvalue, 0.0d);
}
@Test
public void testAddVertexWithPropertyList() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "review", "id", 1,
"comment", "looks good!",
"comment", "LGTM!");
this.mayCommitTx();
vertex = vertex("review", "id", 1);
Assert.assertEquals(ImmutableList.of("looks good!", "LGTM!"),
vertex.value("comment"));
List<Object> props = vertex.value("comment");
Assert.assertEquals(2, props.size());
Assert.assertEquals("looks good!", props.get(0));
Assert.assertEquals("LGTM!", props.get(1));
vertex = graph.addVertex(T.label, "review", "id", 2,
"comment",
ImmutableList.of("looks good 2!", "LGTM!"));
this.mayCommitTx();
vertex = vertex("review", "id", 2);
Assert.assertEquals(ImmutableList.of("looks good 2!", "LGTM!"),
vertex.value("comment"));
props = vertex.value("comment");
Assert.assertEquals(2, props.size());
Assert.assertEquals("looks good 2!", props.get(0));
Assert.assertEquals("LGTM!", props.get(1));
vertex = graph.addVertex(T.label, "review", "id", 3,
"comment",
new String[]{"looks good 3!", "LGTM!"});
this.mayCommitTx();
vertex = vertex("review", "id", 3);
Assert.assertEquals(ImmutableList.of("looks good 3!", "LGTM!"),
vertex.value("comment"));
props = vertex.value("comment");
Assert.assertEquals(2, props.size());
Assert.assertEquals("looks good 3!", props.get(0));
Assert.assertEquals("LGTM!", props.get(1));
}
@Test
public void testAddVertexWithInvalidPropertyList() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "review", "id", 1,
"comment", "looks good!",
"comment", 18);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "review", "id", 2,
"comment", ImmutableList.of("looks good 2!", 18));
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
Object[] comments = new Object[]{"looks good 3!", "3"};
comments[1] = 3;
graph.addVertex(T.label, "review", "id", 3,
"comment", comments);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "review", "id", 3,
"comment", new int[]{1, 2});
});
}
@Test
public void testRemoveLeftRangeIndex() throws InterruptedException {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("updateTime").asLong().create();
schema.vertexLabel("soft").properties("name", "updateTime")
.primaryKeys("name").create();
schema.indexLabel("softByUpdateTime").onV("soft").range()
.by("updateTime").create();
final long testDataCount = 10L;
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "soft", "name", "soft" + i,
"updateTime", i);
}
this.commitTx();
long count = graph.traversal().V()
.has("soft", "updateTime",
ConditionP.gt(0))
.limit(-1)
.count()
.next();
Assert.assertEquals(testDataCount, count);
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "soft", "name", "soft" + i,
"updateTime", 2 * i);
}
this.commitTx();
count = graph.traversal().V()
.has("soft", "updateTime",
ConditionP.gt(0))
.limit(-1)
.count()
.next();
Assert.assertEquals(testDataCount, count);
schema.propertyKey("score").asInt().create();
schema.vertexLabel("developer").properties("name", "age", "score")
.primaryKeys("name").create();
schema.indexLabel("developerByAge").onV("developer").range()
.by("age").create();
schema.indexLabel("developerByScore").onV("developer").range()
.by("score").create();
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "developer", "name", "developer" + i,
"age", i,
"score", i);
}
this.commitTx();
count = graph.traversal().V()
.hasLabel("developer")
.has("age", ConditionP.gt(0))
.has("score", ConditionP.gt(0))
.limit(-1)
.count()
.next();
Assert.assertEquals(testDataCount, count);
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "developer", "name", "developer" + i,
"age", i * 2,
"score", i * 2);
}
this.commitTx();
count = graph.traversal().V()
.hasLabel("developer")
.has("age", ConditionP.gt(0))
.has("score", ConditionP.gt(0))
.limit(-1)
.count()
.next();
Assert.assertEquals(testDataCount, count);
// Wait left index to be removed
Thread.sleep(2000);
count = graph.traversal().V()
.hasLabel("developer")
.has("age", ConditionP.gt(0))
.limit(-1)
.count()
.next();
// Debug stop here to see whether the left index be correctly determined
Assert.assertEquals(testDataCount, count);
// mock test removeLeftIndexIfNeeded
boolean removeLeftIndexOnOverwrite =
Whitebox.getInternalState(params().graphTransaction(),
"removeLeftIndexOnOverwrite");
Whitebox.setInternalState(params().graphTransaction(),
"removeLeftIndexOnOverwrite", true);
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "developer", "name", "developer" + i,
"age", i * 3,
"score", i * 3);
}
this.commitTx();
if (!removeLeftIndexOnOverwrite) {
Whitebox.setInternalState(params().graphTransaction(),
"removeLeftIndexOnOverwrite", false);
}
count = graph.traversal().V()
.hasLabel("developer")
.has("age", ConditionP.gt(0))
.has("score", ConditionP.gt(0))
.limit(-1)
.count()
.next();
Assert.assertEquals(testDataCount, count);
}
@Test
public void testLeftUnionIndex() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("updateTime").asLong().create();
schema.propertyKey("country").asText().create();
schema.vertexLabel("soft").properties("name", "country", "updateTime")
.primaryKeys("name").create();
schema.indexLabel("softByCountryAndUpdateTime").onV("soft").secondary()
.by("country", "updateTime").create();
final long testDataCount = 2L;
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "soft", "name", "soft" + i,
"country", "china", "updateTime", i);
}
this.commitTx();
long count = graph.traversal().V()
.hasLabel("soft")
.has("updateTime", 2L)
.has("country", "china")
.limit(-1)
.count()
.next();
Assert.assertEquals(1, count);
for (int i = 1; i <= testDataCount; i++) {
graph.addVertex(T.label, "soft", "name", "soft" + i,
"country", "china", "updateTime", i * 2);
}
this.commitTx();
count = graph.traversal().V()
.hasLabel("soft")
.has("updateTime", 2L)
.has("country", "china")
.limit(-1)
.count()
.next();
Assert.assertEquals(1L, count);
}
@Test
public void testAddVertexWithPropertySet() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "review", "id", 1,
"contribution", "+1",
"contribution", "+2",
"contribution", "+2");
this.mayCommitTx();
vertex = vertex("review", "id", 1);
Assert.assertEquals(ImmutableSet.of("+1", "+2"),
vertex.value("contribution"));
vertex = graph.addVertex(T.label, "review", "id", 2,
"contribution",
ImmutableSet.of("+1", "+1", "+2"));
this.mayCommitTx();
vertex = vertex("review", "id", 2);
Assert.assertEquals(ImmutableSet.of("+1", "+2"),
vertex.value("contribution"));
}
@Test
public void testAddVertexWithCollectionIndex() {
SchemaManager schema = graph().schema();
schema.propertyKey("tags").asText().valueSet().create();
schema.propertyKey("category").asText().valueSet().create();
schema.propertyKey("country").asText().create();
schema.propertyKey("score").asInt().valueSet().create();
schema.vertexLabel("soft").properties("name", "tags", "score",
"country", "category")
.primaryKeys("name")
.create();
schema.indexLabel("softByTag").onV("soft").by("tags")
.secondary().create();
schema.indexLabel("softByScore").onV("soft").by("score")
.secondary().create();
schema.indexLabel("softByCategory").onV("soft").by("category")
.search().create();
HugeGraph graph = graph();
graph.addVertex(T.label, "soft", "name", "hugegraph",
"country", "china",
"score", ImmutableList.of(5, 4, 3),
"category", ImmutableList.of("graph database", "db"),
"tags", ImmutableList.of("graphdb", "gremlin"));
graph.addVertex(T.label, "soft", "name", "neo4j",
"country", "usa",
"score", ImmutableList.of(5, 4),
"category", ImmutableList.of("graphdb", "database"),
"tags", ImmutableList.of("graphdb", "cypher"));
graph.addVertex(T.label, "soft", "name", "janusgraph",
"country", "usa",
"score", ImmutableList.of(5),
"category",
ImmutableList.of("hello graph", "graph database"),
"tags", ImmutableList.of("graphdb", "gremlin"));
// TODO: test mayCommitTx() after support textContains(collection, str)
this.commitTx();
List<Vertex> vertices;
vertices = graph.traversal().V()
.has("soft", "category",
ConditionP.textContains("hello database"))
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph.traversal().V()
.has("soft", "category",
ConditionP.textContains("graph"))
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertThrows(IllegalStateException.class, () -> {
graph.traversal().V().has("soft", "tags", "gremlin").toList();
});
// query by contains
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("gremlin"))
.toList();
Assert.assertEquals(2, vertices.size());
// secondary-index with list/set of number properties
vertices = graph.traversal().V()
.has("soft", "score", ConditionP.contains(5))
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph.traversal().V()
.has("soft", "name", "hugegraph").toList();
Assert.assertEquals(1, vertices.size());
// add a new tag
Vertex vertex = vertices.get(0);
vertex.property("tags", ImmutableSet.of("new_tag"));
this.commitTx();
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("new_tag"))
.toList();
Assert.assertEquals(1, vertices.size());
// delete tag gremlin
vertex = graph.addVertex(T.label, "soft", "name", "hugegraph",
"country", "china",
"score", ImmutableList.of(5, 4, 3),
"category", ImmutableList.of("hello graph",
"graph database"),
"tags", ImmutableList.of("graphdb",
"new_tag"));
this.mayCommitTx();
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("gremlin"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("new_tag"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("graphdb"))
.toList();
Assert.assertEquals(3, vertices.size());
// remove
vertex.remove();
this.mayCommitTx();
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("new_tag"))
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.has("soft", "tags", ConditionP.contains("graphdb"))
.toList();
Assert.assertEquals(2, vertices.size());
}
@Test
public void testAddVertexWithInvalidPropertySet() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "review", "id", 1,
"contribution", "+1",
"contribution", 2);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "review", "id", 2,
"contribution", ImmutableSet.of("+1", 2));
});
}
@Test
public void testAddVertexWithInvalidVertexLabelType() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, true);
});
}
@Test
public void testAddVertexWithNotExistsVertexLabel() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "not-exists-label");
});
}
@Test
public void testAddVertexWithNotExistsPropKey() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "book", "not-exists-prop", "test");
});
}
@Test
public void testAddVertexWithNullableKeyAbsent() {
Vertex vertex = graph().addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong");
Assert.assertEquals("Baby", vertex.value("name"));
Assert.assertEquals("Hongkong", vertex.value("city"));
}
@Test
public void testAddVertexLabelNewVertexWithNonNullKeysAbsent() {
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().tx().open();
// Absent 'city'
graph().addVertex(T.label, "person", "name", "Baby", "age", 18);
graph().tx().commit();
});
}
@Test
public void testAddVertexWithAppendedNullableKeysAbsent() {
SchemaManager schema = graph().schema();
schema.vertexLabel("person").nullableKeys("city").append();
// Absent 'age' and 'city'
Vertex vertex = graph().addVertex(T.label, "person", "name", "Baby");
Assert.assertEquals("Baby", vertex.value("name"));
this.mayCommitTx();
}
@Test
public void testAddVertexWithDefaultPropertyValue() {
SchemaManager schema = graph().schema();
schema.propertyKey("fav").asText()
.userdata(Userdata.DEFAULT_VALUE, "Movie").create();
schema.propertyKey("cnt").asInt()
.userdata(Userdata.DEFAULT_VALUE, 123).create();
schema.vertexLabel("person")
.properties("fav", "cnt")
.nullableKeys("fav", "cnt").append();
// No 'fav'
Vertex vertex = graph().addVertex(T.label, "person",
"name", "Baby", "city", "Shanghai");
Assert.assertEquals("Baby", vertex.value("name"));
Assert.assertFalse(vertex.values("fav").hasNext());
Assert.assertFalse(vertex.values("age").hasNext());
vertex = graph().vertex(vertex.id());
Assert.assertEquals("Baby", vertex.value("name"));
Assert.assertFalse(vertex.values("fav").hasNext());
Assert.assertFalse(vertex.values("cnt").hasNext());
Assert.assertFalse(vertex.values("age").hasNext());
this.commitTx();
// Exist 'fav' after commit then query
vertex = graph().vertex(vertex.id());
Assert.assertEquals("Baby", vertex.value("name"));
Assert.assertEquals("Movie", vertex.value("fav"));
Assert.assertEquals(123, vertex.value("cnt"));
Assert.assertFalse(vertex.values("age").hasNext());
}
@Test
public void testAddVertexWithNotExistsVertexPropKey() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "book", "age", 12);
});
}
@Test
public void testAddVertexWithoutPrimaryValues() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "book");
});
}
@Test
public void testAddVertexWithPrimaryValuesEmpty() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "book", "name", "");
});
}
@Test
public void testAddVertexWithoutVertexLabel() {
HugeGraph graph = graph();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex("name", "test");
});
}
@Test
public void testAddVertexWithAutomaticIdStrategyButPassedId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useAutomaticId()
.properties("name", "age", "city")
.create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, "123456",
"name", "marko", "age", 18, "city", "Beijing");
});
}
@Test
public void testAddVertexWithAutomaticIdStrategy() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
// May be set forceString=true by config
Whitebox.setInternalState(SnowflakeIdGenerator.instance(graph),
"forceString", false);
schema.vertexLabel("programmer")
.useAutomaticId()
.properties("name", "age", "city")
.create();
Vertex v1 = graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
Vertex v2 = graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
Assert.assertNotEquals(v1.id(), v2.id());
vertices = graph.traversal().V().toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V(v2.id()).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
}
@Test
public void testAddVertexWithAutomaticIdStrategyAndForceStringId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
// May be set forceString=false by config
Whitebox.setInternalState(SnowflakeIdGenerator.instance(graph),
"forceString", true);
schema.vertexLabel("programmer")
.useAutomaticId()
.properties("name", "age", "city")
.create();
Vertex v1 = graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
Vertex v2 = graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
Assert.assertNotEquals(v1.id(), v2.id());
vertices = graph.traversal().V().toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V(v2.id()).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
}
@Test
public void testAddVertexWithPrimaryKeyIdStrategyButPassedId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.usePrimaryKeyId()
.properties("name", "age", "city")
.primaryKeys("name", "age")
.create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, "123456",
"name", "marko", "age", 18, "city", "Beijing");
});
}
@Test
public void testAddVertexWithPrimaryKeyIdStrategy() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.usePrimaryKeyId()
.properties("name", "age", "city")
.primaryKeys("name", "age")
.create();
graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
String programmerId = graph.vertexLabel("programmer").id().asString();
String vid = String.format("%s:%s!%s", programmerId, "marko", "1I");
List<Vertex> vertices = graph.traversal().V(vid).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(vid, vertices.get(0).id().toString());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
}
@Test
public void testAddVertexWithCustomizeStringIdStrategy() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeStringId()
.properties("name", "age", "city")
.create();
graph.addVertex(T.label, "programmer", T.id, "123456", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V("123456").toList();
Assert.assertEquals(1, vertices.size());
Id id = (Id) vertices.get(0).id();
Assert.assertEquals(IdType.STRING, id.type());
Assert.assertEquals("123456", id.asString());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
}
@Test
public void testAddVertexWithCustomizeStringIdStrategyWithoutValidId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeStringId()
.properties("name", "age", "city")
.create();
// Expect id, but no id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
});
// Expect string id, but got number id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, 123456,
"name", "marko", "age", 18, "city", "Beijing");
});
// Expect id length <= 128
Assert.assertThrows(IllegalArgumentException.class, () -> {
String largeId = new String(new byte[128]) + ".";
assert largeId.length() == 129;
graph.addVertex(T.label, "programmer", T.id, largeId,
"name", "marko", "age", 18, "city", "Beijing");
});
}
@Test
public void testAddVertexWithCustomizeNumberIdStrategy() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeNumberId()
.properties("name", "age", "city")
.create();
graph.addVertex(T.label, "programmer", T.id, 123456, "name", "marko",
"age", 18, "city", "Beijing");
graph.addVertex(T.label, "programmer", T.id, 61695499031416832L,
"name", "marko", "age", 19, "city", "Beijing");
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V(123456).toList();
Assert.assertEquals(1, vertices.size());
Id id = (Id) vertices.get(0).id();
Assert.assertEquals(IdType.LONG, id.type());
Assert.assertEquals(123456, id.asLong());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
vertices = graph.traversal().V(61695499031416832L).toList();
Assert.assertEquals(1, vertices.size());
id = (Id) vertices.get(0).id();
Assert.assertEquals(IdType.LONG, id.type());
Assert.assertEquals(61695499031416832L, id.asLong());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 19, "city", "Beijing");
}
@Test
public void testAddVertexWithCustomizeNumberIdStrategyWithoutValidId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeNumberId()
.properties("name", "age", "city")
.create();
// Expect id, but no id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
});
// Expect number id, but got string id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, "123456",
"name", "marko", "age", 18, "city", "Beijing");
});
}
@Test
public void testAddVertexWithCustomizeUuidIdStrategy() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeUuidId()
.properties("name", "age", "city")
.create();
graph.addVertex(T.label, "programmer",
T.id, "835e1153-9281-4957-8691-cf79258e90eb",
"name", "marko", "age", 18, "city", "Beijing");
graph.addVertex(T.label, "programmer",
T.id, UUID.fromString(
"835e1153-9281-4957-8691-cf79258e90eb"),
"name", "marko", "age", 18, "city", "Beijing");
graph.addVertex(T.label, "programmer",
T.id, "835e1153928149578691cf79258e90ee",
"name", "marko", "age", 19, "city", "Beijing");
this.commitTx();
Assert.assertEquals(2L, graph.traversal().V().count().next());
Object uuid = Text.uuid("835e1153928149578691cf79258e90eb");
List<Vertex> vertices = graph.traversal().V(uuid).toList();
Assert.assertEquals(1, vertices.size());
Id id = (Id) vertices.get(0).id();
Assert.assertEquals(IdType.UUID, id.type());
Assert.assertEquals("835e1153-9281-4957-8691-cf79258e90eb",
id.asString());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
uuid = Text.uuid("835e1153-9281-4957-8691-cf79258e90ee");
vertices = graph.traversal().V(uuid).toList();
Assert.assertEquals(1, vertices.size());
id = (Id) vertices.get(0).id();
Assert.assertEquals(IdType.UUID, id.type());
Assert.assertEquals("835e1153-9281-4957-8691-cf79258e90ee",
id.asString());
assertContains(vertices,
T.label, "programmer", "name", "marko",
"age", 19, "city", "Beijing");
}
@Test
public void testAddVertexWithCustomizeUuidIdStrategyWithoutValidId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeUuidId()
.properties("name", "age", "city")
.create();
// Expect id, but no id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", "name", "marko",
"age", 18, "city", "Beijing");
});
// Expect uuid id, but got number id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, 123456,
"name", "marko", "age", 18, "city", "Beijing");
});
// Expect uuid id, but got invalid string id
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "programmer", T.id, "123456",
"name", "marko", "age", 18, "city", "Beijing");
});
}
@Test
public void testAddVertexWithTx() {
HugeGraph graph = graph();
GraphTransaction tx = params().openTransaction();
tx.addVertex(T.label, "book", "name", "java-4");
tx.addVertex(T.label, "book", "name", "java-5");
try {
tx.commit();
} finally {
tx.close();
}
long count = graph.traversal().V().count().next();
Assert.assertEquals(2, count);
}
@Test
public void testAddVertexWithTtl() {
Vertex vertex = graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Beijing");
this.commitTx();
Iterator<Vertex> vertices = graph().vertices(vertex);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().vertices(vertex);
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithTtlAndTtlStartTime() {
Vertex vertex = graph().addVertex(
T.label, "follower", "name",
"Baby", "age", 3, "city", "Beijing",
"birth", graph().now() - 1000L);
this.commitTx();
Iterator<Vertex> vertices = graph().vertices(vertex);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(1100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().vertices(vertex);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(1100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().vertices(vertex);
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithSecondaryIndexAndTtl() {
graph().schema().indexLabel("fanByCity").onV("fan").by("city")
.secondary().ifNotExist().create();
Vertex vertex = graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Beijing");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V()
.has("city", "Beijing");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().traversal().V().has("city", "Beijing");
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithRangeIndexAndTtl() {
graph().schema().indexLabel("fanByAge").onV("fan").by("age")
.range().ifNotExist().create();
Vertex vertex1 = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex2 = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 4, "city", "Beijing");
Vertex vertex3 = graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 5, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex4 = graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 6, "city", "Beijing");
Vertex vertex5 = graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 7, "city", "Beijing");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has("age", 5);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex3, vertices.next());
vertices = graph().traversal().V().has("age", P.gt(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex5, vertices.next());
vertices = graph().traversal().V().has("age", P.gte(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.lt(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex1, vertices.next());
vertices = graph().traversal().V().has("age", P.lte(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().traversal().V().has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gt(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gte(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lt(4));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lte(4));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithShardIndexAndTtl() {
graph().schema().indexLabel("fanByCityAndAge").onV("fan")
.by("city", "age").shard().ifNotExist().create();
Vertex vertex1 = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex2 = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 4, "city", "Beijing");
Vertex vertex3 = graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 5, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex4 = graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 6, "city", "Beijing");
Vertex vertex5 = graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 7, "city", "Beijing");
Vertex vertex6 = graph().addVertex(T.label, "fan", "name", "Baby6",
"age", 5, "city", "Shanghai");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has("city",
"Shanghai");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex6, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex3, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex5, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex1, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithSearchIndexAndTtl() {
graph().schema().indexLabel("fanByCity").onV("fan")
.by("city").search().ifNotExist().create();
Vertex vertex = graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Beijing Haidian");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has(
"city", Text.contains("Haidian"));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertices = graph().traversal().V().has("city",
Text.contains("Haidian"));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddVertexWithUniqueIndexAndTtl() {
graph().schema().indexLabel("fanByCity").onV("fan")
.by("city").unique().ifNotExist().create();
graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Beijing");
this.commitTx();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing");
this.commitTx();
});
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing");
this.commitTx();
}
@Test
public void testOverrideVertexWithSecondaryIndexAndTtl() {
graph().schema().indexLabel("fanByCity").onV("fan").by("city")
.secondary().ifNotExist().create();
Vertex vertex = graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Beijing");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V()
.has("city", "Beijing");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// Override
vertex = graph().addVertex(T.label, "fan", "name", "Baby",
"age", 3, "city", "Shanghai");
this.commitTx();
// Due to overridden vertices are expired,
// query will lead to async delete
vertices = graph().traversal().V().has("city", "Beijing");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All edges are expired after 6s
vertices = graph().traversal().V().has("city", "Beijing");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testOverrideVertexWithRangeIndexAndTtl() {
graph().schema().indexLabel("fanByAge").onV("fan").by("age")
.range().ifNotExist().create();
Vertex vertex1 = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex2 = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 5, "city", "Beijing");
Vertex vertex3 = graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 7, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex4 = graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 9, "city", "Beijing");
Vertex vertex5 = graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 11, "city", "Beijing");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has("age", 7);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex3, vertices.next());
vertices = graph().traversal().V().has("age", P.gt(9));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex5, vertices.next());
vertices = graph().traversal().V().has("age", P.gte(9));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.lt(5));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex1, vertices.next());
vertices = graph().traversal().V().has("age", P.lte(5));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// Override
Vertex vertex6 = graph().addVertex(T.label, "fan", "name", "Baby6",
"age", 4, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex7 = graph().addVertex(T.label, "fan", "name", "Baby7",
"age", 6, "city", "Beijing");
Vertex vertex8 = graph().addVertex(T.label, "fan", "name", "Baby8",
"age", 8, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex9 = graph().addVertex(T.label, "fan", "name", "Baby9",
"age", 10, "city", "Beijing");
Vertex vertex10 = graph().addVertex(T.label, "fan", "name", "Baby10",
"age", 12, "city", "Beijing");
this.commitTx();
/*
* Due to overridden vertices are expired,
* query will lead to async delete
*/
vertices = graph().traversal().V().has("age", 7);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", 8);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex8, vertices.next());
vertices = graph().traversal().V().has("age", P.gt(10));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex10, vertices.next());
vertices = graph().traversal().V().has("age", P.gte(10));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.lt(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex6, vertices.next());
vertices = graph().traversal().V().has("age", P.lte(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All edges are expired after 6s
vertices = graph().traversal().V().has("age", 7);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", 8);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gt(10));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gte(10));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lt(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lte(6));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testOverrideVertexWithShardIndexAndTtl() {
graph().schema().indexLabel("fanByCityAndAge").onV("fan")
.by("city", "age").shard().ifNotExist().create();
Vertex vertex1 = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 1, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex2 = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing");
Vertex vertex3 = graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 5, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex4 = graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 7, "city", "Beijing");
Vertex vertex5 = graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 9, "city", "Beijing");
Vertex vertex6 = graph().addVertex(T.label, "fan", "name", "Baby6",
"age", 5, "city", "Shanghai");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has("city",
"Shanghai");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex6, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex3, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(7));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex5, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(7));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(3));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex1, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(3));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
Vertex vertex7 = graph().addVertex(T.label, "fan", "name", "Baby7",
"age", 2, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex8 = graph().addVertex(T.label, "fan", "name", "Baby8",
"age", 4, "city", "Beijing");
Vertex vertex9 = graph().addVertex(T.label, "fan", "name", "Baby9",
"age", 6, "city", "Beijing");
@SuppressWarnings("unused")
Vertex vertex10 = graph().addVertex(T.label, "fan",
"name", "Baby10", "age", 8,
"city", "Beijing");
Vertex vertex11 = graph().addVertex(T.label, "fan",
"name", "Baby101", "age", 10,
"city", "Beijing");
Vertex vertex12 = graph().addVertex(T.label, "fan",
"name", "Baby12", "age", 6,
"city", "Shenzhen");
this.commitTx();
// Due to overridden vertices are expired, query will lead to async delete
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Shenzhen");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex12, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 6);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex9, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(8));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex11, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(8));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex7, vertices.next());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 6s
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Shenzhen");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 6);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(8));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(8));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testOverrideVertexWithSearchIndexAndTtl() {
graph().schema().indexLabel("fanByCity").onV("fan")
.by("city").search().ifNotExist().create();
Vertex vertex = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing Haidian");
this.commitTx();
Iterator<Vertex> vertices = graph().traversal().V().has(
"city", Text.contains("Haidian"));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
vertex = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Shanghai Pudong");
this.commitTx();
// Due to overridden vertices are expired, query will lead to async delete
vertices = graph().traversal().V().has("city",
Text.contains("Haidian"));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city",
Text.contains("Pudong"));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 6s
vertices = graph().traversal().V().has("city",
Text.contains("Pudong"));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testQueryVertexWithTtlInTx() {
Vertex vertex1 = graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
this.commitTx();
// Add vertices in tx
Vertex vertex2 = graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing");
Iterator<Vertex> vertices = graph().vertices(vertex1);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex1, vertices.next());
vertices = graph().vertices(vertex2);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(vertex2, vertices.next());
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 3s
vertices = graph().vertices(vertex1);
Assert.assertFalse(vertices.hasNext());
vertices = graph().vertices(vertex2);
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testQueryVertexWithSecondaryIndexAndTtlInTx() {
graph().schema().indexLabel("fanByCity").onV("fan").by("city")
.secondary().ifNotExist().create();
graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
this.commitTx();
// Add vertices in tx
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing");
Iterator<Vertex> vertices = graph().traversal().V()
.has("city", "Beijing");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 3s
vertices = graph().traversal().V().has("city", "Beijing");
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testQueryVertexWithRangeIndexAndTtlInTx() {
graph().schema().indexLabel("fanByAge").onV("fan").by("age")
.range().ifNotExist().create();
graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 4, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 5, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 6, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 7, "city", "Beijing");
this.commitTx();
// Add vertices in tx
graph().addVertex(T.label, "fan", "name", "Baby6",
"age", 3, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby7",
"age", 4, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby8",
"age", 5, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby9",
"age", 6, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby10",
"age", 7, "city", "Beijing");
Iterator<Vertex> vertices = graph().traversal().V().has("age", 5);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.gt(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.gte(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(4, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.lt(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("age", P.lte(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(4, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 3s
vertices = graph().traversal().V().has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gt(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.gte(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lt(4));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("age", P.lte(4));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testQueryVertexWithShardIndexAndTtlInTx() {
graph().schema().indexLabel("fanByCityAndAge").onV("fan")
.by("city", "age").shard().ifNotExist().create();
graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 4, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby3",
"age", 5, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby4",
"age", 6, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby5",
"age", 7, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby6",
"age", 5, "city", "Shanghai");
this.commitTx();
// Add vertices in tx
graph().addVertex(T.label, "fan", "name", "Baby7",
"age", 3, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby8",
"age", 4, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby9",
"age", 5, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby10",
"age", 6, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby11",
"age", 7, "city", "Beijing");
graph().addVertex(T.label, "fan", "name", "Baby12",
"age", 5, "city", "Shanghai");
Iterator<Vertex> vertices = graph().traversal().V()
.has("city", "Shanghai");
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(6));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(4, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(4, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 3s
vertices = graph().traversal().V().has("city", "Shanghai");
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", 5);
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gt(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.gte(6));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lt(4));
Assert.assertFalse(vertices.hasNext());
vertices = graph().traversal().V().has("city", "Beijing")
.has("age", P.lte(4));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testQueryVertexWithSearchIndexAndTtlInTx() {
graph().schema().indexLabel("fanByCity").onV("fan")
.by("city").search().ifNotExist().create();
graph().addVertex(T.label, "fan", "name", "Baby1",
"age", 3, "city", "Beijing Haidian");
this.commitTx();
graph().addVertex(T.label, "fan", "name", "Baby2",
"age", 3, "city", "Beijing Haidian");
Iterator<Vertex> vertices = graph().traversal().V().has(
"city", Text.contains("Haidian"));
Assert.assertTrue(vertices.hasNext());
Assert.assertEquals(2, IteratorUtils.count(vertices));
this.commitTx();
try {
Thread.sleep(3100L);
} catch (InterruptedException e) {
// Ignore
}
// All vertices are expired after 3s
vertices = graph().traversal().V().has("city", Text.contains("Haidian"));
Assert.assertFalse(vertices.hasNext());
}
@Test
public void testAddOlapNoneProperties() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
String olapPropName = "olap";
schema.propertyKey(olapPropName)
.asText().valueSingle()
.writeType(WriteType.OLAP_COMMON)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
String language = graph.vertexLabel("language").id().asString();
Id id3 = SplicingIdGenerator.splicing(language, "java");
Id id4 = SplicingIdGenerator.splicing(language, "c++");
Id id5 = SplicingIdGenerator.splicing(language, "python");
String book = graph.vertexLabel("book").id().asString();
Id id6 = SplicingIdGenerator.splicing(book, "java-1");
Id id7 = SplicingIdGenerator.splicing(book, "java-2");
Id id8 = SplicingIdGenerator.splicing(book, "java-3");
Id id9 = SplicingIdGenerator.splicing(book, "java-4");
Id id10 = SplicingIdGenerator.splicing(book, "java-5");
graph.addVertex(T.id, id1.asObject(), olapPropName, "a");
graph.addVertex(T.id, id2.asObject(), olapPropName, "b");
graph.addVertex(T.id, id3.asObject(), olapPropName, "c");
graph.addVertex(T.id, id4.asObject(), olapPropName, "d");
graph.addVertex(T.id, id5.asObject(), olapPropName, "e");
graph.addVertex(T.id, id6.asObject(), olapPropName, "f");
graph.addVertex(T.id, id7.asObject(), olapPropName, "g");
graph.addVertex(T.id, id8.asObject(), olapPropName, "h");
graph.addVertex(T.id, id9.asObject(), olapPropName, "i");
graph.addVertex(T.id, id10.asObject(), olapPropName, "j");
this.commitTx();
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "a").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "c").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "f").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
graph.readMode(GraphReadMode.ALL);
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().has(olapPropName, "a").hasNext();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().has(olapPropName, "c").hasNext();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().has(olapPropName, "f").hasNext();
});
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testAddOlapSecondaryProperties() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
String olapPropName = "wcc";
schema.propertyKey(olapPropName)
.asText().valueSingle()
.writeType(WriteType.OLAP_SECONDARY)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
String language = graph.vertexLabel("language").id().asString();
Id id3 = SplicingIdGenerator.splicing(language, "java");
Id id4 = SplicingIdGenerator.splicing(language, "c++");
Id id5 = SplicingIdGenerator.splicing(language, "python");
String book = graph.vertexLabel("book").id().asString();
Id id6 = SplicingIdGenerator.splicing(book, "java-1");
Id id7 = SplicingIdGenerator.splicing(book, "java-2");
Id id8 = SplicingIdGenerator.splicing(book, "java-3");
Id id9 = SplicingIdGenerator.splicing(book, "java-4");
Id id10 = SplicingIdGenerator.splicing(book, "java-5");
graph.addVertex(T.id, id1.asObject(), olapPropName, "a");
graph.addVertex(T.id, id2.asObject(), olapPropName, "b");
graph.addVertex(T.id, id3.asObject(), olapPropName, "c");
graph.addVertex(T.id, id4.asObject(), olapPropName, "d");
graph.addVertex(T.id, id5.asObject(), olapPropName, "e");
graph.addVertex(T.id, id6.asObject(), olapPropName, "f");
graph.addVertex(T.id, id7.asObject(), olapPropName, "g");
graph.addVertex(T.id, id8.asObject(), olapPropName, "h");
graph.addVertex(T.id, id9.asObject(), olapPropName, "i");
graph.addVertex(T.id, id10.asObject(), olapPropName, "j");
this.commitTx();
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "a").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "c").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, "f").hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
graph.readMode(GraphReadMode.ALL);
List<Vertex> vertices = graph.traversal().V()
.has(olapPropName, "a").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, "c").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id3).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, "f").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id6).next(), vertices.get(0));
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testAddOlapRangeProperties() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
String olapPropName = "pagerank";
schema.propertyKey(olapPropName)
.asDouble().valueSingle()
.writeType(WriteType.OLAP_RANGE)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
String language = graph.vertexLabel("language").id().asString();
Id id3 = SplicingIdGenerator.splicing(language, "java");
Id id4 = SplicingIdGenerator.splicing(language, "c++");
Id id5 = SplicingIdGenerator.splicing(language, "python");
String book = graph.vertexLabel("book").id().asString();
Id id6 = SplicingIdGenerator.splicing(book, "java-1");
Id id7 = SplicingIdGenerator.splicing(book, "java-2");
Id id8 = SplicingIdGenerator.splicing(book, "java-3");
Id id9 = SplicingIdGenerator.splicing(book, "java-4");
Id id10 = SplicingIdGenerator.splicing(book, "java-5");
graph.addVertex(T.id, id1.asObject(), olapPropName, 0.1D);
graph.addVertex(T.id, id2.asObject(), olapPropName, 0.2D);
graph.addVertex(T.id, id3.asObject(), olapPropName, 0.3D);
graph.addVertex(T.id, id4.asObject(), olapPropName, 0.4D);
graph.addVertex(T.id, id5.asObject(), olapPropName, 0.5D);
graph.addVertex(T.id, id6.asObject(), olapPropName, 0.6D);
graph.addVertex(T.id, id7.asObject(), olapPropName, 0.7D);
graph.addVertex(T.id, id8.asObject(), olapPropName, 0.8D);
graph.addVertex(T.id, id9.asObject(), olapPropName, 0.9D);
graph.addVertex(T.id, id10.asObject(), olapPropName, 1.0D);
this.commitTx();
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, 0.1D).hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, 0.3D).hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V().has(olapPropName, 0.6D).hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
graph.traversal().V(id1).next();
graph.readMode(GraphReadMode.ALL);
List<Vertex> vertices = graph.traversal().V()
.has(olapPropName, 0.1D).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, 0.3D).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id3).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, 0.6D).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id6).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, P.gt(0.9D)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id10).next(),
vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, P.lt(0.2D)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V().has(olapPropName, P.gte(0.9D))
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id9).next()));
Assert.assertTrue(vertices.contains(
graph.traversal().V(id10).next()));
vertices = graph.traversal().V().has(olapPropName, P.lte(0.2D))
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id1).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id2).next()));
vertices = graph.traversal().V()
.has(olapPropName, P.inside(0.2D, 0.9D)).toList();
Assert.assertEquals(6, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id3).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id4).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id5).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id6).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id7).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id8).next()));
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testAddOlapRangeAndOlapSecondaryProperties() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("pagerank")
.asDouble().valueSingle()
.writeType(WriteType.OLAP_RANGE)
.ifNotExist().create();
schema.propertyKey("wcc")
.asText().valueSingle()
.writeType(WriteType.OLAP_SECONDARY)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
String language = graph.vertexLabel("language").id().asString();
Id id3 = SplicingIdGenerator.splicing(language, "java");
Id id4 = SplicingIdGenerator.splicing(language, "c++");
Id id5 = SplicingIdGenerator.splicing(language, "python");
String book = graph.vertexLabel("book").id().asString();
Id id6 = SplicingIdGenerator.splicing(book, "java-1");
Id id7 = SplicingIdGenerator.splicing(book, "java-2");
Id id8 = SplicingIdGenerator.splicing(book, "java-3");
Id id9 = SplicingIdGenerator.splicing(book, "java-4");
Id id10 = SplicingIdGenerator.splicing(book, "java-5");
graph.addVertex(T.id, id1.asObject(), "pagerank", 0.1D);
graph.addVertex(T.id, id2.asObject(), "pagerank", 0.2D);
graph.addVertex(T.id, id3.asObject(), "pagerank", 0.3D);
graph.addVertex(T.id, id4.asObject(), "pagerank", 0.4D);
graph.addVertex(T.id, id5.asObject(), "pagerank", 0.5D);
graph.addVertex(T.id, id6.asObject(), "pagerank", 0.6D);
graph.addVertex(T.id, id7.asObject(), "pagerank", 0.7D);
graph.addVertex(T.id, id8.asObject(), "pagerank", 0.8D);
graph.addVertex(T.id, id9.asObject(), "pagerank", 0.9D);
graph.addVertex(T.id, id10.asObject(), "pagerank", 1.0D);
this.commitTx();
graph.addVertex(T.id, id1.asObject(), "wcc", "a");
graph.addVertex(T.id, id2.asObject(), "wcc", "a");
graph.addVertex(T.id, id3.asObject(), "wcc", "c");
graph.addVertex(T.id, id4.asObject(), "wcc", "c");
graph.addVertex(T.id, id5.asObject(), "wcc", "c");
graph.addVertex(T.id, id6.asObject(), "wcc", "f");
graph.addVertex(T.id, id7.asObject(), "wcc", "f");
graph.addVertex(T.id, id8.asObject(), "wcc", "f");
graph.addVertex(T.id, id9.asObject(), "wcc", "f");
graph.addVertex(T.id, id10.asObject(), "wcc", "f");
this.commitTx();
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("pagerank", 0.1D)
.has("wcc", "a")
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("pagerank", 0.3D)
.has("wcc", "b")
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("pagerank", 0.6D)
.has("wcc", "f")
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
graph.readMode(GraphReadMode.ALL);
List<Vertex> vertices = graph.traversal().V()
.has("pagerank", 0.1D)
.has("wcc", "a")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", 0.3D)
.has("wcc", "c")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id3).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", 0.6D)
.has("wcc", "f")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id6).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.gt(0.9D))
.has("wcc", "f")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id10).next(),
vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.lt(0.2D))
.has("wcc", "a")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.gte(0.9D))
.has("wcc", "f")
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id9).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id10).next()));
vertices = graph.traversal().V()
.has("pagerank", P.lte(0.2D))
.has("wcc", "a")
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id1).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id2).next()));
vertices = graph.traversal().V()
.has("pagerank", P.inside(0.2D, 0.9D))
.has("wcc", "c")
.toList();
Assert.assertEquals(3, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id3).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id4).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id5).next()));
vertices = graph.traversal().V()
.has("pagerank", P.inside(0.2D, 0.9D))
.has("wcc", "f")
.toList();
Assert.assertEquals(3, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id6).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id7).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id8).next()));
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testQueryOlapRangeAndRegularSecondaryProperties() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.indexLabel("authorByAge").onV("author").range()
.by("age").create();
schema.indexLabel("authorByLived").onV("author").secondary()
.by("lived").create();
schema.propertyKey("pagerank")
.asDouble().valueSingle()
.writeType(WriteType.OLAP_RANGE)
.ifNotExist().create();
schema.propertyKey("wcc")
.asText().valueSingle()
.writeType(WriteType.OLAP_SECONDARY)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
graph.addVertex(T.id, id1.asObject(), "pagerank", 0.1D);
graph.addVertex(T.id, id2.asObject(), "pagerank", 0.2D);
this.commitTx();
graph.addVertex(T.id, id1.asObject(), "wcc", "a");
graph.addVertex(T.id, id2.asObject(), "wcc", "b");
this.commitTx();
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("pagerank", 0.1D)
.has("lived", "Canadian")
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("wcc", "a")
.has("age", 62)
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
Assert.assertEquals(GraphReadMode.OLTP_ONLY, graph.readMode());
Assert.assertThrows(NotAllowException.class, () -> {
graph.traversal().V()
.has("pagerank", 0.1D)
.has("age", 62)
.hasNext();
}, e -> {
Assert.assertContains("Not allowed to query by olap property key",
e.getMessage());
});
graph.readMode(GraphReadMode.ALL);
List<Vertex> vertices = graph.traversal().V()
.has("pagerank", 0.1D)
.has("lived", "Canadian")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.lte(0.1D))
.has("age", P.gte(62))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.lte(0.1D))
.has("age", P.gte(62))
.has("lived", "Canadian")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id1).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("age", P.gt(5))
.has("wcc", "b")
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(graph.traversal().V(id2).next(), vertices.get(0));
vertices = graph.traversal().V()
.has("pagerank", P.gte(0.1D))
.has("age", P.gte(10))
.toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(graph.traversal().V(id1).next()));
Assert.assertTrue(vertices.contains(graph.traversal().V(id2).next()));
Set<Vertex> vertexSet = graph.traversal().V()
.has("pagerank", P.lte(0.9D))
.has("wcc", P.within("a", "b"))
.has("age", P.gt(20))
.has("lived", P.within("Canadian",
"California"))
.toSet();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertexSet.contains(graph.traversal().V(id1).next()));
Assert.assertTrue(vertexSet.contains(graph.traversal().V(id2).next()));
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testQueryOlapWithUpdates() {
Assume.assumeTrue("Not support olap properties",
storeFeatures().supportsOlapProperties());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("pagerank")
.asDouble().valueSingle()
.writeType(WriteType.OLAP_RANGE)
.ifNotExist().create();
this.init10VerticesAndCommit();
String author = graph.vertexLabel("author").id().asString();
Id id1 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(1));
Id id2 = SplicingIdGenerator.splicing(author,
LongEncoding.encodeNumber(2));
graph.addVertex(T.id, id1.asObject(), "pagerank", 0.1D);
graph.addVertex(T.id, id2.asObject(), "pagerank", 0.2D);
graph.readMode(GraphReadMode.ALL);
// FIXME: expect to throw error here
// Assert.assertThrows(IllegalArgumentException.class, () -> {
// graph.traversal().V().has("pagerank", 0.1D).toList();
// }, e -> {
// Assert.assertContains("not allowed to query by olap " +
// "when there are uncommitted records",
// e.toString());
// });
this.commitTx();
List<Vertex> vertices = graph.traversal().V()
.has("pagerank", 0.2D)
.toList();
Assert.assertEquals(1, vertices.size());
graph.readMode(GraphReadMode.OLTP_ONLY);
}
@Test
public void testQueryAll() {
HugeGraph graph = graph();
init10Vertices();
// Query all
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(10, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
assertContains(vertices, T.label, "language", "name", "java");
assertContains(vertices, T.label, "book", "name", "java-1");
}
@Test
public void testQueryAllWithGraphAPI() {
HugeGraph graph = graph();
init10Vertices();
// Query all
List<Vertex> vertices = ImmutableList.copyOf(graph.vertices());
Assert.assertEquals(10, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
assertContains(vertices, T.label, "language", "name", "java");
assertContains(vertices, T.label, "book", "name", "java-1");
}
@Test
public void testQueryAllWithLimit() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
// Query all with limit
List<Vertex> vertices = graph.traversal().V().limit(6).toList();
Assert.assertEquals(6, vertices.size());
}
@Test
public void testQueryAllWithLimitAfterUncommittedDelete() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
// Query all with limit after delete
graph.traversal().V().limit(6).drop().iterate();
// Query count with uncommitted records
graph.traversal().V().count().next();
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Query with limit
graph.traversal().V().limit(3).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Query with offset
graph.traversal().V().range(1, -1).toList();
});
// Query all with limit after delete once
this.commitTx();
Assert.assertEquals(4L, graph.traversal().V().count().next());
List<Vertex> vertices = graph.traversal().V().limit(3).toList();
Assert.assertEquals(3, vertices.size());
// Query all with limit after delete twice
graph.traversal().V().limit(3).drop().iterate();
this.commitTx();
vertices = graph.traversal().V().limit(3).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryAllWithLimitAfterUncommittedInsert() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
// Query all with limit after insert
graph.addVertex(T.label, "author", "id", 3,
"name", "test", "age", 88,
"lived", "California");
// Query count with uncommitted records
Assert.assertEquals(11L, graph.traversal().V().count().next());
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Query with limit
graph.traversal().V().limit(3).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Query with offset
graph.traversal().V().range(1, -1).toList();
});
// Do commit
this.commitTx();
// Query count
Assert.assertEquals(11L, graph.traversal().V().count().next());
// Query with limit
Assert.assertEquals(3L, graph.traversal().V().limit(3).toList().size());
// Query with offset
Assert.assertEquals(10L, graph.traversal().V().range(1, -1).toList().size());
}
@Test
public void testQueryAllWithLimitByQueryVertices() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
Query query = new Query(HugeType.VERTEX);
query.limit(1);
Iterator<Vertex> iter = graph.vertices(query);
List<Vertex> vertices = IteratorUtils.list(iter);
Assert.assertEquals(1, vertices.size());
CloseableIterator.closeIterator(iter);
}
@Test
public void testQueryAllWithLimit0() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
// Query all with limit 0
List<Vertex> vertices = graph.traversal().V().limit(0).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryAllWithNoLimit() {
HugeGraph graph = graph();
init10Vertices();
// Query all with limit -1 (mean no-limit)
List<Vertex> vertices = graph.traversal().V().limit(-1).toList();
Assert.assertEquals(10, vertices.size());
}
@Test
public void testQueryAllWithIllegalLimit() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().limit(-2).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().limit(-18).toList();
});
}
@Test
public void testQueryAllWithOffset() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
List<Vertex> vertices = graph.traversal().V().range(8, 100).toList();
Assert.assertEquals(2, vertices.size());
List<Vertex> vertices2 = graph.traversal().V().range(8, -1).toList();
Assert.assertEquals(vertices, vertices2);
}
@Test
public void testQueryAllWithOffsetAndLimit() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
List<Vertex> vertices = graph.traversal().V().range(8, 9).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V().range(0, 4).toList();
Assert.assertEquals(4, vertices.size());
vertices = graph.traversal().V().range(-2, 4).toList();
Assert.assertEquals(4, vertices.size());
vertices = graph.traversal().V().range(10, -1).toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().range(0, -1).toList();
Assert.assertEquals(10, vertices.size());
vertices = graph.traversal().V().range(-2, -1).toList();
Assert.assertEquals(10, vertices.size());
}
@Test
public void testQueryAllWithOffsetAndLimitWithMultiTimes() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
List<Vertex> vertices = graph.traversal().V()
.range(1, 6)
.range(4, 8)
.toList();
// [5, 6)
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.range(1, -1)
.range(6, 8)
.toList();
// [7, 9)
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V()
.range(1, 6)
.range(6, 8)
.toList();
// [7, 6) will be converted to NoneStep by EarlyLimitStrategy
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.range(1, 6)
.range(7, 8)
.toList();
// [8, 6) will be converted to NoneStep by EarlyLimitStrategy
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryAllWithIllegalOffsetOrLimit() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().range(8, 7).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().range(-1, -2).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().range(0, -2).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().range(-4, -2).toList();
});
}
@Test
public void testQueryWithSplicingId() {
HugeGraph graph = graph();
init10Vertices();
List<Vertex> vertices = graph.traversal().V().toList();
String bookId = graph.vertexLabel("book").id().asString();
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-1")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-3")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-5")));
}
@Test
public void testQueryById() {
HugeGraph graph = graph();
init10Vertices();
String authorId = graph.vertexLabel("author").id().asString();
// Query vertex by id
Id id = SplicingIdGenerator.splicing(authorId, "11");
List<Vertex> vertices = graph.traversal().V(id).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
vertices = graph.traversal().V().hasId(id).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
vertices = graph.traversal().V().has(T.id, id).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
}
@Test
public void testQueryByIdNotFound() {
HugeGraph graph = graph();
init10Vertices();
// Query vertex by id which not exists
Id id = SplicingIdGenerator.splicing("author", "not-exists-id");
Assert.assertTrue(graph.traversal().V(id).toList().isEmpty());
Assert.assertThrows(NoSuchElementException.class, () -> {
graph.traversal().V(id).next();
});
}
@Test
public void testQueryByIdWithGraphAPI() {
HugeGraph graph = graph();
init10Vertices();
Object id = graph.traversal().V().toList().get(0).id();
List<Vertex> vertices = ImmutableList.copyOf(graph.vertices(id));
Assert.assertEquals(1, vertices.size());
vertices = ImmutableList.copyOf(graph.vertices(id, id));
Assert.assertEquals(2, vertices.size());
}
@Test
public void testQueryByIdWithGraphAPIAndNotCommittedUpdate() {
HugeGraph graph = graph();
init10Vertices();
Vertex vertex = graph.traversal().V()
.hasLabel("author")
.has("id", 1).next();
Object id = vertex.id();
Assert.assertTrue(graph.vertices(id).hasNext());
Assert.assertTrue(graph.vertices(id, id).hasNext());
vertex.property("age", 66);
List<Vertex> vertices = ImmutableList.copyOf(graph.vertices(id));
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(66, (int) vertices.get(0).value("age"));
vertices = ImmutableList.copyOf(graph.vertices(id, id));
Assert.assertEquals(2, vertices.size());
Assert.assertEquals(66, (int) vertices.get(1).value("age"));
}
@Test
public void testQueryByIdWithGraphAPIAndNotCommittedRemoved() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author").toList();
Vertex vertex1 = vertices.get(0);
Vertex vertex2 = vertices.get(1);
Assert.assertTrue(graph.vertices(vertex1.id()).hasNext());
Assert.assertTrue(graph.vertices(vertex2.id()).hasNext());
vertex1.remove();
vertex2.remove();
Assert.assertFalse(graph.vertices(vertex1.id()).hasNext());
Assert.assertFalse(graph.vertices(vertex2.id()).hasNext());
Assert.assertFalse(graph.vertices(vertex1.id(), vertex2.id())
.hasNext());
graph.tx().rollback();
Assert.assertTrue(graph.vertices(vertex1.id()).hasNext());
Assert.assertTrue(graph.vertices(vertex2.id()).hasNext());
Assert.assertTrue(graph.vertices(vertex1.id(), vertex2.id()).hasNext());
}
@Test
public void testQueryByInvalidSysprop() {
HugeGraph graph = graph();
init10Vertices();
List<Vertex> vertices = graph.traversal().V().hasLabel("author")
.has("id", 1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex = vertices.get(0);
Id author = graph.vertexLabel(vertex.label()).id();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("author").has("ID", 1).toList();
}, e -> {
Assert.assertContains("Undefined property key: 'ID'",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("author").has("NAME", "n1").toList();
}, e -> {
Assert.assertContains("Undefined property key: 'NAME'",
e.getMessage());
});
Assert.assertThrows(HugeException.class, () -> {
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
query.eq(HugeKeys.LABEL, author);
query.query((Id) vertex.id());
graph.vertices(query).hasNext();
}, e -> {
Assert.assertContains("Not supported querying by id and conditions",
e.getMessage());
});
Assert.assertThrows(HugeException.class, () -> {
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
query.eq(HugeKeys.LABEL, author);
query.eq(HugeKeys.NAME, "n1");
graph.vertices(query).hasNext();
}, e -> {
Assert.assertContains("Not supported querying vertices by",
e.getMessage());
Assert.assertContains("NAME == n1", e.getMessage());
});
Assert.assertThrows(HugeException.class, () -> {
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
query.eq(HugeKeys.LABEL, author);
query.eq(HugeKeys.NAME, "n2");
query.query(Condition.eq(IdGenerator.of("fake"), "n3"));
graph.vertices(query).hasNext();
}, e -> {
Assert.assertContains("Can't do index query with [",
e.getMessage());
Assert.assertContains("LABEL == ", e.getMessage());
Assert.assertContains("NAME == n2", e.getMessage());
});
}
@Test
public void testQueryByLabel() {
HugeGraph graph = graph();
init10Vertices();
// Query by vertex label
List<Vertex> vertices = graph.traversal().V().hasLabel("book").toList();
String bookId = graph.vertexLabel("book").id().asString();
Assert.assertEquals(5, vertices.size());
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-1")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-2")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-3")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-4")));
Assert.assertTrue(Utils.containsId(vertices,
SplicingIdGenerator.splicing(bookId, "java-5")));
}
@Test
public void testQueryByLabelWithLimit() {
HugeGraph graph = graph();
this.init10VerticesAndCommit();
// Query by vertex label with limit
List<Vertex> vertices = graph.traversal().V().hasLabel("book")
.limit(3).toList();
Assert.assertEquals(3, vertices.size());
// Query by vertex label with limit
graph.traversal().V().hasLabel("book").limit(3).drop().iterate();
this.commitTx();
vertices = graph.traversal().V().hasLabel("book")
.limit(3).toList();
Assert.assertEquals(2, vertices.size());
}
@Test
public void testQueryByLabelNotExists() {
HugeGraph graph = graph();
init10Vertices();
// Query by not exists vertex label
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("xx").toList();
});
}
@Test
public void testQueryByLabelAndKeyName() {
HugeGraph graph = graph();
init10Vertices();
// Query by vertex label and key-name
List<Vertex> vertices = graph.traversal().V().hasLabel("language")
.has("dynamic").toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "language", "name", "python", "dynamic", true);
}
@Test
public void testQueryByPrimaryValues() {
HugeGraph graph = graph();
init10Vertices();
// Query vertex by primary-values
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author")
.has("id", 1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
}
@Test
public void testQueryByPrimaryValuesAndProps() {
HugeGraph graph = graph();
init10Vertices();
// Query vertex by primary-values
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author").has("id", 1)
.has("name", "James Gosling").toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
vertices = graph.traversal().V().hasLabel("author")
.has("id", 1).has("name", "fake-name").toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryFilterByPropName() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support CONTAINS_KEY query",
storeFeatures().supportsQueryWithContainsKey());
init10Vertices();
VertexLabel language = graph.vertexLabel("language");
PropertyKey dynamic = graph.propertyKey("dynamic");
// Query vertex by condition (does contain the property name?)
ConditionQuery q = new ConditionQuery(HugeType.VERTEX);
q.eq(HugeKeys.LABEL, language.id());
q.key(HugeKeys.PROPERTIES, dynamic.id());
List<Vertex> vertices = ImmutableList.copyOf(graph.vertices(q));
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "language", "name", "python", "dynamic", true);
// Query vertex by condition (does contain the property name?)
q = new ConditionQuery(HugeType.VERTEX);
q.key(HugeKeys.PROPERTIES, dynamic.id());
vertices = ImmutableList.copyOf(graph.vertices(q));
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "language", "name", "python", "dynamic", true);
}
@Test
public void testQueryByHasKey() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support CONTAINS_KEY query",
storeFeatures().supportsQueryWithContainsKey());
init10Vertices();
List<Vertex> vertices = graph.traversal().V()
.hasLabel("language")
.hasKey("dynamic")
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "language", "name", "python",
"dynamic", true);
vertices = graph.traversal().V().hasKey("age").toList();
Assert.assertEquals(2, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "Canadian");
assertContains(vertices,
T.label, "author", "id", 2,
"name", "Guido van Rossum", "age", 61,
"lived", "California");
}
@Test
public void testQueryByHasKeys() {
HugeGraph graph = graph();
init10Vertices();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("language")
.hasKey("dynamic", "name").toList();
});
}
@Test
public void testQueryByHasValue() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support CONTAINS query",
storeFeatures().supportsQueryWithContains());
init10Vertices();
List<Vertex> vertices = graph.traversal().V()
.hasLabel("language").hasValue(true)
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "language", "name", "python",
"dynamic", true);
vertices = graph.traversal().V().hasValue(62).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "Canadian");
}
@Test
public void testQueryByHasValues() {
HugeGraph graph = graph();
init10Vertices();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("language")
.hasValue("python", "java").toList();
});
}
@Test
public void testQueryByStringPropWithOneResult() {
// city is "Taipei"
HugeGraph graph = graph();
initPersonIndex(true);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("city", "Taipei")
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "person", "name", "Hebe",
"city", "Taipei", "age", 21);
}
@Test
public void testQueryByStringPropWithMultiResults() {
// NOTE: InMemoryDBStore would fail due to it not support index ele-ids
HugeGraph graph = graph();
initPersonIndex(true);
init5Persons();
// city is "Beijing"
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("city", "Beijing").toList();
Assert.assertEquals(3, vertices.size());
assertContains(vertices,
T.label, "person", "name", "James",
"city", "Beijing", "age", 19);
assertContains(vertices,
T.label, "person", "name", "Tom Cat",
"city", "Beijing", "age", 20);
assertContains(vertices,
T.label, "person", "name", "Lisa",
"city", "Beijing", "age", 20);
// city is "Beijing" && limit 2
vertices = graph.traversal().V().hasLabel("person")
.has("city", "Beijing").limit(2).toList();
Assert.assertEquals(2, vertices.size());
// limit after delete
graph.traversal().V().hasLabel("person")
.has("city", "Beijing").limit(2)
.drop().iterate();
this.commitTx();
vertices = graph.traversal().V().hasLabel("person")
.has("city", "Beijing").limit(2).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByIntPropWithOneResult() {
// age = 19
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", 19).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "person", "name", "James",
"city", "Beijing", "age", 19);
}
@Test
public void testQueryByIntPropWithMultiResults() {
// age = 20
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", 20).toList();
Assert.assertEquals(2, vertices.size());
assertContains(vertices,
T.label, "person", "name", "Tom Cat",
"city", "Beijing", "age", 20);
assertContains(vertices,
T.label, "person", "name", "Lisa",
"city", "Beijing", "age", 20);
}
@Test
public void testQueryByIntPropWithNonResult() {
// age = 18
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", 18).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByIntPropWithDifferentDataType() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().has("age", 21).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().has("age", 21.0).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().has("age", "21").toList();
});
}
@Test
public void testQueryByIntPropWithNegativeNumber() {
HugeGraph graph = graph();
initPersonIndex(false);
graph.addVertex(T.label, "person", "name", "Louise",
"city", "Hongkong", "age", 17,
"birth", Utils.date("2012-01-01"));
graph.addVertex(T.label, "person", "name", "Sean",
"city", "Beijing", "age", -10,
"birth", Utils.date("2029-01-01"));
List<Vertex> vertices = graph.traversal().V().has("age", -10).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "person", "name", "Sean",
"city", "Beijing", "age", -10,
"birth", Utils.date("2029-01-01"));
vertices = graph.traversal().V()
.has("age", P.between(-11, 0))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Sean", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("age", P.gt(-11)).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V().has("age", P.gte(-10)).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V().has("age", P.gt(-10)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Louise", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("age", P.gt(-9)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Louise", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("age", P.lt(-10)).toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().has("age", P.lte(-10)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Sean", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("age", P.lt(0)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Sean", vertices.get(0).value("name"));
}
@Test
public void testQueryByIntPropUsingLtWithOneResult() {
// age < 19
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.lt(19)).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
}
@Test
public void testQueryByIntPropUsingLtWithMultiResults() {
// age < 21
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.lt(21)).toList();
Assert.assertEquals(4, vertices.size());
}
@Test
public void testQueryByIntPropUsingLteWithMultiResults() {
// age <= 20
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.lte(20)).toList();
Assert.assertEquals(4, vertices.size());
}
@Test
public void testQueryByIntPropUsingGtWithOneResult() {
// age > 20
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.gt(20)).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByIntPropUsingGtWithMultiResults() {
// age > 1
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.gt(1)).toList();
Assert.assertEquals(5, vertices.size());
}
@Test
public void testQueryByIntPropUsingGtWithNonResult() {
// age > 30
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.gt(30)).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByIntPropUsingGteWithMultiResults() {
// age >= 20
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.gte(20)).toList();
Assert.assertEquals(3, vertices.size());
}
@Test
public void testQueryByIntPropUsingInsideWithOneResult() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 3 < age && age < 20 (that's age == 19)
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(3, 20)).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(19, vertices.get(0).property("age").value());
}
@Test
public void testQueryByIntPropUsingInsideWithMultiResults() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 19 < age && age < 21 (that's age == 20)
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(19, 21)).toList();
Assert.assertEquals(2, vertices.size());
// 3 < age && age < 21 (that's age == 19 or age == 20)
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(3, 21)).toList();
Assert.assertEquals(3, vertices.size());
// 0 < age && age < 22 (that's all)
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(0, 22)).toList();
Assert.assertEquals(5, vertices.size());
}
@Test
public void testQueryByIntPropUsingInsideWithNonResult() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 3 < age && age < 19
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(3, 19)).toList();
Assert.assertEquals(0, vertices.size());
// 0 < age && age < 3
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(0, 3)).toList();
Assert.assertEquals(0, vertices.size());
// 20 < age && age < 21
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(20, 21)).toList();
Assert.assertEquals(0, vertices.size());
// 21 < age && age < 25
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(21, 25)).toList();
Assert.assertEquals(0, vertices.size());
// 21 < age && age < 20
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.inside(21, 20)).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByIntPropUsingBetweenWithOneResult() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 3 <= age && age < 19 (that's age == 3)
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 19)).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByIntPropUsingBetweenWithMultiResults() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 19 <= age && age < 21
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(19, 21)).toList();
Assert.assertEquals(3, vertices.size());
// 3 <= age && age < 21
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 21)).toList();
Assert.assertEquals(4, vertices.size());
// 3 <= age && age < 21 && limit 3
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 21)).limit(3).toList();
Assert.assertEquals(3, vertices.size());
// limit after delete
graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 21)).limit(3)
.drop().iterate();
this.commitTx();
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 21)).limit(3).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByIntPropUsingBetweenAfterPropOverride() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// -1 <= age && age < 21
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(-1, 21)).toList();
Assert.assertEquals(4, vertices.size());
// override vertex without age (in memory)
graph.addVertex(T.label, "person", "name", "Baby","city", "Hongkong");
// -1 <= age && age < 21
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(-1, 21)).toList();
Assert.assertEquals(3, vertices.size());
// override vertex without age (in backend) and make left index
graph.addVertex(T.label, "person", "name", "Baby","city", "Hongkong")
.remove(); // avoid merge property mode
this.mayCommitTx();
// query again after commit
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(-1, 21)).toList();
Assert.assertEquals(3, vertices.size());
}
@Test
public void testQueryByIntPropUsingBetweenWithNonResult() {
Assume.assumeTrue("Not support range condition query",
storeFeatures().supportsQueryWithRangeCondition());
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
// 4 <= age && age < 19
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(4, 19)).toList();
Assert.assertEquals(0, vertices.size());
// 3 <= age && age < 3
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(3, 3)).toList();
Assert.assertEquals(0, vertices.size());
// 21 <= age && age < 20
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.between(21, 20)).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByIntProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("int").asInt().create();
schema.vertexLabel("number").primaryKeys("id")
.properties("id", "int").create();
schema.indexLabel("numberByInt").range()
.onV("number").by("int").create();
graph().addVertex(T.label, "number", "id", 1, "int", 0);
graph().addVertex(T.label, "number", "id", 2, "int", 12345678);
graph().addVertex(T.label, "number", "id", 3, "int", 1000000001L);
graph().addVertex(T.label, "number", "id", 4, "int", -1);
graph().addVertex(T.label, "number", "id", 5,
"int", Integer.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 6,
"int", Integer.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 7,
"int", Integer.MAX_VALUE - 1);
graph().addVertex(T.label, "number", "id", 8,
"int", Integer.MIN_VALUE + 1);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("number")
.has("int", 0).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 1, "int", 0);
vertices = graph.traversal().V().hasLabel("number")
.has("int", 12345678).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 2, "int", 12345678);
vertices = graph.traversal().V().hasLabel("number")
.has("int", 1000000001L).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 3, "int", 1000000001);
vertices = graph.traversal().V().hasLabel("number")
.has("int", -1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 4, "int", -1);
vertices = graph.traversal().V().hasLabel("number")
.has("int", Integer.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 5,
"int", Integer.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("int", Integer.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 6,
"int", Integer.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("int", Integer.MAX_VALUE - 1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 7,
"int", Integer.MAX_VALUE - 1);
vertices = graph.traversal().V().hasLabel("number")
.has("int", Integer.MIN_VALUE + 1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 8,
"int", Integer.MIN_VALUE + 1);
// query by null property
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V().hasLabel("person")
.has("age", (Object) null).toList();
}, e -> {
Assert.assertContains("Invalid data type of query value",
e.getMessage());
});
}
@Test
public void testQueryByLongProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("long").asLong().create();
schema.vertexLabel("number").primaryKeys("id")
.properties("id", "long").create();
schema.indexLabel("numberByLong").range()
.onV("number").by("long").create();
final long largeLong = 9123456789087654321L;
graph().addVertex(T.label, "number", "id", 1, "long", 0L);
graph().addVertex(T.label, "number", "id", 2, "long", 7L);
graph().addVertex(T.label, "number", "id", 3, "long", 1000000001);
graph().addVertex(T.label, "number", "id", 4, "long", -1L);
graph().addVertex(T.label, "number", "id", 5, "long", largeLong);
graph().addVertex(T.label, "number", "id", 6, "long", -largeLong);
graph().addVertex(T.label, "number", "id", 7, "long", Long.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 8, "long", Long.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 9,
"long", Long.MAX_VALUE - 1);
graph().addVertex(T.label, "number", "id", 10,
"long", Long.MIN_VALUE + 1);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("number")
.has("long", 0).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 1, "long", 0L);
vertices = graph.traversal().V().hasLabel("number")
.has("long", 7).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 2, "long", 7L);
vertices = graph.traversal().V().hasLabel("number")
.has("long", 1000000001).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 3,
"long", 1000000001L);
vertices = graph.traversal().V().hasLabel("number")
.has("long", -1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 4, "long", -1L);
vertices = graph.traversal().V().hasLabel("number")
.has("long", largeLong).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 5,
"long", largeLong);
vertices = graph.traversal().V().hasLabel("number")
.has("long", -largeLong).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 6,
"long", -largeLong);
vertices = graph.traversal().V().hasLabel("number")
.has("long", Long.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 7,
"long", Long.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("long", Long.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 8,
"long", Long.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("long", Long.MAX_VALUE - 1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 9,
"long", Long.MAX_VALUE - 1);
vertices = graph.traversal().V().hasLabel("number")
.has("long", Long.MIN_VALUE + 1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 10,
"long", Long.MIN_VALUE + 1);
}
@Test
public void testQueryByFloatProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("float").asFloat().create();
schema.vertexLabel("number").primaryKeys("id")
.properties("id", "float").create();
schema.indexLabel("numberByFloat").range()
.onV("number").by("float").create();
final float secondBiggest = 0x1.fffffdP+127f;
final float secondSmallest = 0x0.000003P-126f;
graph().addVertex(T.label, "number", "id", 1, "float", 7);
graph().addVertex(T.label, "number", "id", 2, "float", 3.14f);
graph().addVertex(T.label, "number", "id", 3, "float", 3.141592f);
graph().addVertex(T.label, "number", "id", 4, "float", 1234.567d);
graph().addVertex(T.label, "number", "id", 5,
"float", Float.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 6,
"float", -Float.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 7,
"float", Float.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 8,
"float", -Float.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 9,
"float", secondBiggest);
graph().addVertex(T.label, "number", "id", 10,
"float", -secondBiggest);
graph().addVertex(T.label, "number", "id", 11,
"float", secondSmallest);
graph().addVertex(T.label, "number", "id", 12,
"float", -secondSmallest);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("number")
.has("float", 7).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 1, "float", 7f);
vertices = graph.traversal().V().hasLabel("number")
.has("float", 3.14f).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 2, "float", 3.14f);
vertices = graph.traversal().V().hasLabel("number")
.has("float", 3.141592f).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 3,
"float", 3.141592f);
vertices = graph.traversal().V().hasLabel("number")
.has("float", 1234.567d).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 4,
"float", 1234.567f);
vertices = graph.traversal().V().hasLabel("number")
.has("float", Float.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 5,
"float", Float.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("float", -Float.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 6,
"float", -Float.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("float", Float.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 7,
"float", Float.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("float", -Float.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 8,
"float", -Float.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("float", secondBiggest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 9,
"float", secondBiggest);
vertices = graph.traversal().V().hasLabel("number")
.has("float", -secondBiggest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 10,
"float", -secondBiggest);
vertices = graph.traversal().V().hasLabel("number")
.has("float", secondSmallest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 11,
"float", secondSmallest);
vertices = graph.traversal().V().hasLabel("number")
.has("float", -secondSmallest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 12,
"float", -secondSmallest);
}
@Test
public void testQueryByDoubleProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("double").asDouble().create();
schema.vertexLabel("number").primaryKeys("id")
.properties("id", "double").create();
schema.indexLabel("numberByDouble").range()
.onV("number").by("double").create();
final double max7 = Double.valueOf(String.valueOf(Float.MAX_VALUE));
/*
* The double precision type typically has a range of around 1E-307 to
* 1E+308 with a precision of at least 15 digits. (postgresql)
* https://www.postgresql.org/docs/9.5/datatype-numeric.html#DATATYPE-NUMERIC-TABLE
*/
final double max15 = new BigDecimal(Double.MAX_VALUE)
.movePointLeft(308)
.setScale(15, BigDecimal.ROUND_DOWN)
.movePointRight(308)
.doubleValue(); // 1.797693134862315E308
final double min15 = new BigDecimal(1.234567890987654321d)
.setScale(15, BigDecimal.ROUND_DOWN)
.movePointLeft(307)
.doubleValue(); // 1.234567890987654E-307
graph().addVertex(T.label, "number", "id", 1, "double", 7);
graph().addVertex(T.label, "number", "id", 2, "double", 3.14f);
graph().addVertex(T.label, "number", "id", 3, "double", Math.PI);
graph().addVertex(T.label, "number", "id", 4,
"double", 12345678901234.567d); // 12345678901234.566
graph().addVertex(T.label, "number", "id", 5, "double", max7);
graph().addVertex(T.label, "number", "id", 6, "double", -max7);
graph().addVertex(T.label, "number", "id", 7, "double", max15);
graph().addVertex(T.label, "number", "id", 8, "double", -max15);
graph().addVertex(T.label, "number", "id", 9, "double", min15);
graph().addVertex(T.label, "number", "id", 10, "double", -min15);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("number")
.has("double", 7).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 1, "double", 7d);
vertices = graph.traversal().V().hasLabel("number")
.has("double", 3.14f).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 2, "double", 3.14d);
vertices = graph.traversal().V().hasLabel("number")
.has("double", Math.PI).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 3, "double", Math.PI);
vertices = graph.traversal().V().hasLabel("number")
.has("double", 12345678901234.567d).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 4,
"double", 12345678901234.567d);
vertices = graph.traversal().V().hasLabel("number")
.has("double", Float.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 5, "double", max7);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -Float.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 6, "double", -max7);
vertices = graph.traversal().V().hasLabel("number")
.has("double", max15).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 7, "double", max15);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -max15).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 8, -max15);
vertices = graph.traversal().V().hasLabel("number")
.has("double", min15).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 9, "double", min15);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -min15).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 10, -min15);
}
@Test
public void testQueryByDoublePropertyWithMaxMinValue() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("double").asDouble().create();
schema.vertexLabel("number").primaryKeys("id")
.properties("id", "double").create();
schema.indexLabel("numberByDouble").range()
.onV("number").by("double").create();
final double secondBiggest = 0x1.ffffffffffffeP+1023;
final double secondSmallest = 0x0.0000000000002P-1022;
graph().addVertex(T.label, "number", "id", 0,
"double", 0.123456789012345678901d);
graph().addVertex(T.label, "number", "id", 1,
"double", Double.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 2,
"double", -Double.MAX_VALUE);
graph().addVertex(T.label, "number", "id", 3,
"double", Double.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 4,
"double", -Double.MIN_VALUE);
graph().addVertex(T.label, "number", "id", 5,
"double", secondBiggest);
graph().addVertex(T.label, "number", "id", 6,
"double", -secondBiggest);
graph().addVertex(T.label, "number", "id", 7,
"double", secondSmallest);
graph().addVertex(T.label, "number", "id", 8,
"double", -secondSmallest);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("number")
.has("double", 0.123456789012345678901d)
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 0,
"double", 0.123456789012345678901d);
vertices = graph.traversal().V().hasLabel("number")
.has("double", Double.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 1,
"double", Double.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -Double.MAX_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 2,
"double", -Double.MAX_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("double", Double.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 3,
"double", Double.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -Double.MIN_VALUE).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 4,
"double", -Double.MIN_VALUE);
vertices = graph.traversal().V().hasLabel("number")
.has("double", secondBiggest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 5,
"double", secondBiggest);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -secondBiggest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 6,
"double", -secondBiggest);
vertices = graph.traversal().V().hasLabel("number")
.has("double", secondSmallest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 7,
"double", secondSmallest);
vertices = graph.traversal().V().hasLabel("number")
.has("double", -secondSmallest).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "number", "id", 8,
"double", -secondSmallest);
}
@Test
public void testQueryByDateProperty() {
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = null;
Date[] dates = new Date[]{
Utils.date("2012-01-01 00:00:00.000"),
Utils.date("2013-01-01 00:00:00.000"),
Utils.date("2014-01-01 00:00:00.000"),
Utils.date("2015-01-01 00:00:00.000"),
Utils.date("2016-01-01 00:00:00.000")
};
vertices = graph.traversal().V().hasLabel("person")
.has("birth", dates[0])
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(dates[0], vertices.get(0).value("birth"));
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.gt(dates[0]))
.toList();
Assert.assertEquals(4, vertices.size());
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[3], dates[4]))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(dates[3], vertices.get(0).value("birth"));
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[1], dates[4]))
.toList();
Assert.assertEquals(3, vertices.size());
// limit
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[1], dates[4]))
.limit(2).toList();
Assert.assertEquals(2, vertices.size());
Assert.assertEquals(dates[1], vertices.get(0).value("birth"));
Assert.assertEquals(dates[2], vertices.get(1).value("birth"));
// limit after delete
graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[1], dates[4]))
.limit(2).drop().iterate();
this.commitTx();
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[1], dates[4]))
.limit(2).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(dates[3], vertices.get(0).value("birth"));
}
@Test
public void testQueryByDatePropertyInString() {
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = null;
String[] dates = new String[]{
"2012-01-01 00:00:00.000",
"2013-01-01 00:00:00.000",
"2014-01-01 00:00:00.000",
"2015-01-01 00:00:00.000",
"2016-01-01 00:00:00.000"
};
vertices = graph.traversal().V().hasLabel("person")
.has("birth", dates[0])
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(Utils.date(dates[0]),
vertices.get(0).value("birth"));
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.gt(dates[0]))
.toList();
Assert.assertEquals(4, vertices.size());
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[3], dates[4]))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(Utils.date(dates[3]),
vertices.get(0).value("birth"));
}
@Test
@SuppressWarnings("unchecked")
public void testQueryByDatePropertyWithUnion() {
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices = null;
String[] dates = new String[]{
"2012-01-01 00:00:00.000",
"2013-01-01 00:00:00.000",
"2014-01-01 00:00:00.000",
"2015-01-01 00:00:00.000",
"2016-01-01 00:00:00.000"
};
vertices = g.V()
.hasLabel("person")
.union(__.<Vertex>has("birth", dates[0]))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(Utils.date(dates[0]),
vertices.get(0).value("birth"));
vertices = g.V()
.hasLabel("person")
.union(__.<Vertex>has("birth", P.gt(dates[0])))
.toList();
Assert.assertEquals(4, vertices.size());
vertices = g.V()
.hasLabel("person")
.union(__.<Vertex>has("birth", P.lt(dates[1])),
__.<Vertex>has("birth", P.gt(dates[3])))
.toList();
Assert.assertEquals(2, vertices.size());
}
@Test
public void testQueryByDatePropertyInMultiFormatString() {
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = null;
String[] dates = new String[]{
"2012-01-01",
"2013-01-01 00:00:00.000",
"2014-01-01 00:00:00.000",
"2015-01-01 00:00:00",
"2016-01-01 00:00:00.000"
};
vertices = graph.traversal().V().hasLabel("person")
.has("birth", dates[0])
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(Utils.date(dates[0]),
vertices.get(0).value("birth"));
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.gt(dates[0]))
.toList();
Assert.assertEquals(4, vertices.size());
vertices = graph.traversal().V().hasLabel("person")
.has("birth", P.between(dates[3], dates[4]))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(Utils.date(dates[3]),
vertices.get(0).value("birth"));
}
@Test
public void testQueryByUUIDProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("uuid").asUUID().create();
schema.vertexLabel("user").primaryKeys("id")
.properties("id", "uuid").create();
schema.indexLabel("userByUuid").secondary()
.onV("user").by("uuid").create();
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.randomUUID();
graph().addVertex(T.label, "user", "id", 1, "uuid", uuid1);
graph().addVertex(T.label, "user", "id", 2, "uuid", uuid2);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("user")
.has("uuid", uuid1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "user", "id", 1, "uuid", uuid1);
vertices = graph.traversal().V().hasLabel("user")
.has("uuid", uuid2).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "user", "id", 2, "uuid", uuid2);
}
@Test
public void testQueryByBlobProperty() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("blob").asBlob().create();
schema.vertexLabel("user").primaryKeys("id")
.properties("id", "blob").create();
schema.indexLabel("userByBlob").secondary()
.onV("user").by("blob").create();
Blob blob1 = Blob.wrap(new byte[]{97, 49, 50, 51, 52});
Blob blob2 = Blob.wrap(new byte[]{97, 98, 50, 51, 52});
graph().addVertex(T.label, "user", "id", 1, "blob", blob1);
graph().addVertex(T.label, "user", "id", 2, "blob", blob2);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("user")
.has("blob", blob1).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "user", "id", 1, "blob", blob1);
vertices = graph.traversal().V().hasLabel("user")
.has("blob", blob2).toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices, T.label, "user", "id", 2, "blob", blob2);
}
@Test
public void testQueryByTextContainsProperty() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.search().by("lived").create();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco Bay Area");
// Uncommitted
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.toList();
Assert.assertEquals(1, vertices.size());
// Committed
this.commitTx();
vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "San Francisco Bay Area");
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().hasLabel("author")
.has("lived", "Bay Area")
.toList();
}, e -> {
Assert.assertContains("may not match secondary condition",
e.getMessage());
});
}
@Test
public void testQueryByTextContainsAndExactMatchProperty() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLivedSearch").onV("author")
.search().by("lived").create();
graph.schema().indexLabel("authorByLivedSecondary").onV("author")
.secondary().by("lived").create();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco Bay Area");
this.mayCommitTx();
// By authorByLivedSearch index
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.toList();
Assert.assertEquals(1, vertices.size());
// By authorByLivedSecondary index
vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", "San Francisco Bay Area")
.toList();
Assert.assertEquals(1, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "San Francisco Bay Area");
vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", "Bay Area")
.toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByTextContainsPropertyOrderByMatchedCount() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.search().by("lived").create();
graph.addVertex(T.label, "author", "id", 1, "name", "Tank", "age", 16,
"lived", "Beijing");
graph.addVertex(T.label, "author", "id", 2, "name", "Dim", "age", 40,
"lived", "Shenzhen area");
graph.addVertex(T.label, "author", "id", 3, "name", "Tom", "age", 19,
"lived", "New York Bay");
graph.addVertex(T.label, "author", "id", 4, "name", "Jason", "age", 20,
"lived", "Tokyo Bay");
graph.addVertex(T.label, "author", "id", 5, "name", "James", "age", 62,
"lived", "San Francisco Bay Area");
this.commitTx();
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.toList();
Assert.assertEquals(4, vertices.size());
Assert.assertEquals("James", vertices.get(0).value("name"));
Assert.assertEquals("Tom", vertices.get(1).value("name"));
Assert.assertEquals("Jason", vertices.get(2).value("name"));
Assert.assertEquals("Dim", vertices.get(3).value("name"));
assertContains(vertices,
T.label, "author", "id", 2, "name", "Dim",
"age", 40, "lived", "Shenzhen area");
assertContains(vertices,
T.label, "author", "id", 3, "name", "Tom",
"age", 19, "lived", "New York Bay");
assertContains(vertices,
T.label, "author", "id", 4, "name", "Jason",
"age", 20, "lived", "Tokyo Bay");
assertContains(vertices,
T.label, "author", "id", 5, "name", "James",
"age", 62, "lived", "San Francisco Bay Area");
vertices = graph.traversal().V().hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.limit(1)
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("James", vertices.get(0).value("name"));
vertices = graph.traversal().V().hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.skip(1)
.toList();
Assert.assertEquals(3, vertices.size());
Assert.assertEquals("Tom", vertices.get(0).value("name"));
Assert.assertEquals("Jason", vertices.get(1).value("name"));
Assert.assertEquals("Dim", vertices.get(2).value("name"));
vertices = graph.traversal().V().hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.skip(2).limit(1)
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("Jason", vertices.get(0).value("name"));
}
@Test
public void testQueryByTextContainsPropertyOrderByMatchedCountWithPaging() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.search().by("lived").create();
graph.addVertex(T.label, "author", "id", 1, "name", "Tank", "age", 16,
"lived", "Beijing");
graph.addVertex(T.label, "author", "id", 2, "name", "Dim", "age", 40,
"lived", "Shenzhen area");
graph.addVertex(T.label, "author", "id", 3, "name", "Tom", "age", 19,
"lived", "New York Bay");
graph.addVertex(T.label, "author", "id", 4, "name", "Jason", "age", 20,
"lived", "Tokyo Bay");
graph.addVertex(T.label, "author", "id", 5, "name", "James", "age", 62,
"lived", "San Francisco Bay Area");
this.commitTx();
List<Vertex> vertices = graph.traversal().V()
.hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.has("~page", "").limit(2)
.toList();
Assert.assertEquals(2, vertices.size());
assertContains(vertices,
T.label, "author", "id", 3, "name", "Tom",
"age", 19, "lived", "New York Bay");
assertContains(vertices,
T.label, "author", "id", 4, "name", "Jason",
"age", 20, "lived", "Tokyo Bay");
}
@Test
public void testQueryByTextContainsPropertyWithLeftIndex() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.search().by("lived").create();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco Bay Area");
this.commitTx();
// Override the origin vertex with different property value
// and then lead to index left
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco, California, U.S.");
this.commitTx();
// Set breakpoint to observe the store before and after this statement
List<Vertex> vertices = graph.traversal().V().hasLabel("author")
.has("lived", Text.contains("Bay Area"))
.toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByNeq() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived1").onV("author")
.secondary().by("lived").create();
graph.schema().indexLabel("authorByLived2").onV("author")
.search().by("lived").create();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco Bay Area");
this.mayCommitTx();
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().hasLabel("author")
.has("lived",P.neq("Beijing"))
.toList();
}, e -> {
Assert.assertEquals("Don't accept query based on properties " +
"[lived] that are not indexed in label " +
"'author', may not match secondary" +
"/not-equal condition", e.getMessage());
});
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().has("lived",P.neq("Beijing"))
.toList();
}, e -> {
Assert.assertContains("Don't accept query based on properties " +
"[lived] that are not indexed in any label",
e.getMessage());
Assert.assertContains("may not match not-equal condition",
e.getMessage());
});
}
@Test
public void testQueryWithMultiLayerConditions() {
HugeGraph graph = graph();
initPersonIndex(false);
init5Persons();
List<Object> vertices = graph.traversal().V().hasLabel("person").has(
"age",
P.not(P.lte(10).and(P.not(P.between(11, 20))))
.and(P.lt(29).or(P.eq(35)).or(P.gt(45)))
).values("name").toList();
// There is duplicate results with OR condition
Assert.assertEquals(5, vertices.size());
Set<String> names = ImmutableSet.of("Hebe", "James",
"Tom Cat", "Lisa");
for (Object name : vertices) {
Assert.assertTrue(names.contains(name));
}
}
@Test
public void testQueryByIntPropOfOverrideVertex() {
HugeGraph graph = graph();
initPersonIndex(false);
graph.addVertex(T.label, "person", "name", "Zhangyi",
"city", "Beijing", "age", 28);
graph.addVertex(T.label, "person", "name", "Zhangyi",
"city", "Hongkong", "age", 29);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().has("age", 28).toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().has("age", 29).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByStringPropOfOverrideVertex() {
HugeGraph graph = graph();
initPersonIndex(true);
graph.addVertex(T.label, "person", "name", "Zhangyi",
"city", "Beijing", "age", 28);
graph.addVertex(T.label, "person", "name", "Zhangyi",
"city", "Hongkong", "age", 29);
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().has("city", "Beijing")
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryWithTxNotCommittedByNoCondition() {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
graph.addVertex(T.label, "person", "name", "james",
"age", 19, "city", "Hongkong");
List<Vertex> vertices;
vertices = graph.traversal().V().toList();
Assert.assertEquals(2, vertices.size());
graph.tx().rollback();
vertices = graph.traversal().V().toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryWithTxNotCommittedById() {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
List<Vertex> vertices;
String personId = graph.vertexLabel("person").id().asString();
String vid = SplicingIdGenerator.splicing(personId, "marko").asString();
vertices = graph.traversal().V(vid).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(vid, vertices.get(0).id().toString());
graph.tx().rollback();
vertices = graph.traversal().V(personId + ":marko").toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryWithTxNotCommittedByIntProp() {
HugeGraph graph = graph();
initPersonIndex(false);
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
List<Vertex> vertices;
vertices = graph.traversal().V().has("age", 18).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(18, (int) vertices.get(0).<Integer>value("age"));
graph.tx().rollback();
vertices = graph.traversal().V("person:marko").toList();
Assert.assertEquals(0, vertices.size());
// TODO: add test for: append, eliminate, remove
}
@Test
public void testQueryWithTxNotCommittedByIdInOtherThread()
throws InterruptedException {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
AtomicInteger size = new AtomicInteger(-1);
Thread t = new Thread(() -> {
try {
List<Vertex> vertices = graph.traversal()
.V("person:marko")
.toList();
size.set(vertices.size());
} finally {
params().closeTx();
}
});
t.start();
t.join();
Assert.assertEquals(0, size.get());
}
@Test
public void testQueryWithTxNotCommittedUpdatedProp() {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
Vertex v = graph.addVertex(T.label, "person", "name", "james",
"age", 19, "city", "Hongkong");
this.commitTx();
v.property("age", 20);
// Don't commit
List<Vertex> vertices = graph.traversal().V()
.where(__.values("age").is(20))
.toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals(v.id(), vertices.get(0).id());
}
@Test
public void testQueryByJointIndexes() {
HugeGraph graph = graph();
initPersonIndex(true);
this.init5Persons();
List<Vertex> vertices;
// results count < 2
vertices = graph.traversal().V().has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("city", "Hongkong").has("age", 2).toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.has("city", "Taipei").has("age", 3).toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.has("city", "Hongkong").has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("city", "Hongkong").has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("city", "Hongkong").has("age", 3)
.skip(1).toList();
Assert.assertEquals(0, vertices.size());
// results count >= 2
vertices = graph.traversal().V().has("age", 20).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V().has("age", 19).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V().has("city", "Beijing").toList();
Assert.assertEquals(3, vertices.size());
vertices = graph.traversal().V()
.has("city", "Beijing").has("age", P.lt(21)).toList();
Assert.assertEquals(3, vertices.size());
Object tx = Whitebox.invoke(graph.getClass(),
"graphTransaction", graph);
Object old = Whitebox.getInternalState(tx,
"indexTx.indexIntersectThresh");
try {
for (int i = 1; i < 6; i++) {
Whitebox.setInternalState(tx,
"indexTx.indexIntersectThresh", i);
vertices = graph.traversal().V()
.has("city", "Beijing").has("age", 20).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V()
.has("city", "Beijing").has("age", 20)
.skip(1).toList();
Assert.assertEquals(1, vertices.size());
}
} finally {
Whitebox.setInternalState(tx, "indexTx.indexIntersectThresh", old);
}
}
@Test
public void testQueryByJointIndexesAndCompositeIndexForOneLabel() {
initPersonIndex(true);
graph().addVertex(T.label, "person", "name", "Tom",
"city", "Hongkong", "age", 3);
this.commitTx();
List<Vertex> vertices;
vertices = graph().traversal().V().has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V().has("city", "Hongkong")
.has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
/*
* NOTE: may block if not commit records:
* Lock [hugegraph_il_delete:3] is locked by other operation
*/
graph().schema().indexLabel("personByCityAndAge").onV("person")
.by("city", "age").ifNotExist().create();
vertices = graph().traversal().V().has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V().has("city", "Hongkong")
.has("age", 3).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesAndCompositeIndexForMultiLabel() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog").properties("name", "age", "city")
.primaryKeys("name").nullableKeys("age").create();
schema.indexLabel("dogByCityAndAge").onV("dog")
.by("city", "age").create();
schema.vertexLabel("cat").properties("name", "age", "city")
.primaryKeys("name").nullableKeys("age").create();
schema.indexLabel("catByCity").onV("cat").secondary()
.by("city").create();
schema.indexLabel("catByAge").onV("cat").range()
.by("age").create();
graph().addVertex(T.label, "dog", "name", "Tom",
"city", "Hongkong", "age", 3);
graph().addVertex(T.label, "cat", "name", "Baby",
"city", "Hongkong", "age", 3);
this.mayCommitTx();
List<Vertex> vertices;
vertices = graph().traversal().V().has("age", 3)
.has("city", "Hongkong").toList();
Assert.assertEquals(2, vertices.size());
Set<String> labels = new HashSet<>();
labels.add(vertices.get(0).label());
labels.add(vertices.get(1).label());
Set<String> expectedLabels = ImmutableSet.of("dog", "cat");
Assert.assertEquals(expectedLabels, labels);
}
@Test
public void testQueryByJointIndexesOnlyWithCompositeIndex() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog").properties("name", "age", "city")
.nullableKeys("age").create();
schema.indexLabel("dogByNameAndCity").onV("dog").secondary()
.by("name", "city").create();
schema.indexLabel("dogByCityAndAge").onV("dog").secondary()
.by("city", "age").create();
graph().addVertex(T.label, "dog", "name", "Tom",
"city", "Hongkong", "age", 3);
this.mayCommitTx();
List<Vertex> vertices = graph().traversal().V().has("age", 3)
.has("city", "Hongkong")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesWithRangeIndex() {
initPersonIndex(true);
graph().addVertex(T.label, "person", "name", "Tom",
"city", "Hongkong", "age", 3);
List<Vertex> vertices;
vertices = graph().traversal().V().has("age", P.gt(2))
.has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesWithCompositeIndexIncludeOtherField() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog").properties("name", "age", "city")
.nullableKeys("age").create();
schema.indexLabel("dogByAge").onV("dog").range().by("age").create();
schema.indexLabel("dogByCityAndName").onV("dog").secondary()
.by("city", "name").create();
graph().addVertex(T.label, "dog", "name", "Tom",
"city", "Hongkong", "age", 3);
this.mayCommitTx();
List<Vertex> vertices = graph().traversal().V().has("age", P.gt(2))
.has("city", "Hongkong").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesWithOnlyRangeIndexes() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog").properties("name", "age", "weight").create();
schema.indexLabel("dogByAge").onV("dog").range().by("age").create();
schema.indexLabel("dogByWeight").onV("dog").range().by("weight")
.create();
graph().addVertex(T.label, "dog", "name", "Tom",
"age", 8, "weight", 3);
this.mayCommitTx();
List<Vertex> vertices = graph().traversal().V().has("age", P.gt(2))
.has("weight", P.lt(10)).toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesWithSearchAndRangeIndexes() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog").properties("name", "age", "description")
.create();
schema.indexLabel("dogByAge").onV("dog")
.range().by("age").create();
schema.indexLabel("dogByDescription").onV("dog")
.search().by("description").create();
graph().addVertex(T.label, "dog", "name", "Bella", "age", 1,
"description", "black hair and eyes");
graph().addVertex(T.label, "dog", "name", "Daisy", "age", 2,
"description", "yellow hair yellow tail");
graph().addVertex(T.label, "dog", "name", "Coco", "age", 3,
"description", "yellow hair golden tail");
this.commitTx();
List<Vertex> vertices;
vertices = graph().traversal().V()
.has("age", P.gte(2))
.has("description", Text.contains("yellow hair"))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(2))
.has("description", Text.contains("yellow hair"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.toList();
Assert.assertEquals(2, vertices.size());
}
@Test
public void testQueryByJointIndexesWithSearchAndRangeAndSecondaryIndexes() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog")
.properties("name", "age", "description", "city")
.create();
schema.indexLabel("dogByAge").onV("dog")
.range().by("age").create();
schema.indexLabel("dogByDescription").onV("dog")
.search().by("description")
.create();
schema.indexLabel("dogByCity").onV("dog")
.secondary().by("city").create();
graph().addVertex(T.label, "dog", "name", "Bella", "age", 1,
"city", "Beijing",
"description", "black hair and eyes");
graph().addVertex(T.label, "dog", "name", "Daisy", "age", 2,
"city", "Shanghai",
"description", "yellow hair yellow tail");
graph().addVertex(T.label, "dog", "name", "Coco", "age", 3,
"city", "Shanghai",
"description", "yellow hair golden tail");
this.commitTx();
List<Vertex> vertices;
vertices = graph().traversal().V()
.has("age", P.gte(2))
.has("description", Text.contains("yellow hair"))
.has("city", "Shanghai")
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(2))
.has("description", Text.contains("yellow hair"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(2))
.has("description", Text.contains("yellow hair"))
.has("city", "Beijing")
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.has("city", "Beijing")
.toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByJointIndexesWithTwoSearchAndOneRangeIndexes() {
SchemaManager schema = graph().schema();
schema.vertexLabel("dog")
.properties("name", "age", "description", "city")
.create();
schema.indexLabel("dogByAge").onV("dog")
.range().by("age").create();
schema.indexLabel("dogByDescription").onV("dog")
.search().by("description")
.create();
schema.indexLabel("dogByCity").onV("dog")
.search().by("city").create();
graph().addVertex(T.label, "dog", "name", "Bella", "age", 1,
"city", "Beijing Haidian",
"description", "black hair and eyes");
graph().addVertex(T.label, "dog", "name", "Daisy", "age", 2,
"city", "Shanghai Zhangjiang",
"description", "yellow hair yellow tail");
graph().addVertex(T.label, "dog", "name", "Coco", "age", 3,
"city", "Shanghai Pudong",
"description", "yellow hair golden tail");
this.commitTx();
List<Vertex> vertices;
vertices = graph().traversal().V()
.has("description", Text.contains("yellow hair"))
.has("city", Text.contains("Shanghai"))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gte(2))
.has("description", Text.contains("yellow hair"))
.has("city", Text.contains("Zhangjiang"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(2))
.has("description", Text.contains("yellow hair"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(2))
.has("description", Text.contains("yellow hair"))
.has("city", Text.contains("Beijing"))
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.has("city", Text.contains("Beijing"))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("age", P.gt(0))
.has("description", Text.contains("black golden"))
.has("city", Text.contains("Chaoyang"))
.toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByJointIndexesWithSearchAndTwoRangeIndexesAndWithin() {
SchemaManager schema = graph().schema();
schema.propertyKey("type").asInt().ifNotExist().create();
schema.propertyKey("kid").asInt().ifNotExist().create();
schema.propertyKey("name").asText().ifNotExist().create();
schema.propertyKey("confirmType").asInt().ifNotExist().create();
schema.vertexLabel("test")
.properties("confirmType", "name", "kid", "type")
.nullableKeys("confirmType", "name", "type")
.primaryKeys("kid")
.ifNotExist().create();
schema.indexLabel("test_by_type")
.onV("test").by("type")
.range()
.ifNotExist().create();
schema.indexLabel("test_by_confirmType")
.onV("test").by("confirmType")
.range()
.ifNotExist().create();
schema.indexLabel("test_by_name")
.onV("test").by("name")
.search()
.ifNotExist().create();
HugeGraph graph = graph();
graph.addVertex(T.label, "test", "name", "诚信",
"confirmType", 0, "type", 0, "kid", 0);
graph.addVertex(T.label, "test", "name", "诚信",
"confirmType", 1, "type", 1, "kid", 1);
graph.addVertex(T.label, "test", "name", "诚信文明",
"confirmType", 2, "type", 1, "kid", 2);
graph.addVertex(T.label, "test", "name", "诚信文明",
"confirmType", 3, "type", 1, "kid", 3);
this.mayCommitTx();
List<Vertex> vertices;
vertices = graph().traversal().V()
.has("type", 1)
.has("confirmType", P.within(0, 1, 2, 3))
.has("name", Text.contains("诚信"))
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("type", 1)
.has("confirmType", P.within(0, 1, 2, 3))
.has("name", Text.contains("文明"))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("type", 0)
.has("confirmType", P.within(0, 1, 3))
.has("name", Text.contains("诚信"))
.toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryByShardIndex() {
SchemaManager schema = graph().schema();
schema.indexLabel("personByCityAndAge").onV("person").shard()
.by("city", "age").create();
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "p1",
"city", "Hongkong", "age", 15);
graph.addVertex(T.label, "person", "name", "p2",
"city", "Hongkong", "age", 18);
graph.addVertex(T.label, "person", "name", "p3",
"city", "Beijing", "age", 21);
graph.addVertex(T.label, "person", "name", "p4",
"city", "Beijing", "age", 23);
graph.addVertex(T.label, "person", "name", "p5",
"city", "Beijing", "age", 29);
this.mayCommitTx();
List<Vertex> vertices = graph().traversal().V()
.has("city", "Hongkong")
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("city", "Hongkong")
.has("age", 15).toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("city", "Hongkong")
.has("age", P.between(10, 20)).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.has("age", P.between(20, 30)).toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.has("age", P.lt(29)).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.has("age", P.lte(29)).toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.has("age", P.gt(21)).toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("city", "Beijing")
.has("age", P.gte(21)).toList();
Assert.assertEquals(3, vertices.size());
}
@Test
public void testQueryByShardIndexWithMoreStringMoreNumericFields() {
SchemaManager schema = graph().schema();
schema.propertyKey("province").asText().create();
schema.vertexLabel("user")
.properties("province", "city", "age", "weight")
.create();
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 20, "weight", 60);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 25, "weight", 60);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 30, "weight", 60);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 30, "weight", 70);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 30, "weight", 80);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Jinan", "age", 30, "weight", 90);
graph().addVertex(T.label, "user", "province", "Shandong", "city",
"Qingdao", "age", 20, "weight", 60);
graph().addVertex(T.label, "user", "province", "Guangdong", "city",
"Guangzhou", "age", 20, "weight", 60);
graph().addVertex(T.label, "user", "province", "Guangdong", "city",
"Guangzhou", "age", 31, "weight", 90);
graph().addVertex(T.label, "user", "province", "Guangdong", "city",
"Foshan", "age", 35, "weight", 60);
graph().addVertex(T.label, "user", "province", "Guangdong", "city",
"Foshan", "age", 38, "weight", 70);
graph().addVertex(T.label, "user", "province", "Guangdong", "city",
"Foshan", "age", 38, "weight", 80);
schema.indexLabel("userByProvinceCityAgeWeight").onV("user").shard()
.by("province", "city", "age", "weight").create();
// Query by prefix "province"
List<Vertex> vertices = graph().traversal().V()
.has("province", "Shandong")
.toList();
Assert.assertEquals(7, vertices.size());
vertices = graph().traversal().V()
.has("province", "Guangdong")
.toList();
Assert.assertEquals(5, vertices.size());
// Query by prefix "province", "city"
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.toList();
Assert.assertEquals(6, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Qingdao")
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Guangdong")
.has("city", "Guangzhou")
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("province", "Guangdong")
.has("city", "Foshan")
.toList();
Assert.assertEquals(3, vertices.size());
// Query by prefix "province", "city", "age"
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 20)
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 25)
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.toList();
Assert.assertEquals(4, vertices.size());
// Query by prefix "province", "city" and range "age"
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.lt(25))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.lte(25))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.gt(25))
.toList();
Assert.assertEquals(4, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.gte(25))
.toList();
Assert.assertEquals(5, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.between(25, 31))
.toList();
Assert.assertEquals(5, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", P.between(20, 31))
.toList();
Assert.assertEquals(6, vertices.size());
// Query by prefix "province", "city", "age", "weight"
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", 60)
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", 70)
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", 80)
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", 90)
.toList();
Assert.assertEquals(1, vertices.size());
// Query by prefix "province", "city", "age" and range "weight"
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.lt(80))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.lte(80))
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.gt(80))
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.gte(80))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.between(80, 91))
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.between(70, 91))
.toList();
Assert.assertEquals(3, vertices.size());
vertices = graph().traversal().V()
.has("province", "Shandong")
.has("city", "Jinan")
.has("age", 30)
.has("weight", P.between(60, 91))
.toList();
Assert.assertEquals(4, vertices.size());
// Invalid query
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("city", "Jinan")
.toList();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("age", 30)
.toList();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("weight", 60)
.toList();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("city", "Jinan")
.has("age", 30)
.toList();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("province", "Shandong")
.has("age", 30)
.toList();
});
Assert.assertThrows(NoIndexException.class, () -> {
graph().traversal().V()
.has("province", "Shandong")
.has("age", P.between(10, 30))
.toList();
});
}
@Test
public void testQueryCount() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.secondary().by("lived").create();
graph.schema().indexLabel("authorByAge").onV("author")
.range().by("age").create();
init10Vertices();
initPersonIndex(true);
init100Persons();
GraphTraversalSource g = graph.traversal();
Assert.assertEquals(110L, g.V().count().next());
Assert.assertEquals(2L, g.V().hasLabel("author").count().next());
Assert.assertEquals(3L, g.V().hasLabel("language").count().next());
Assert.assertEquals(5L, g.V().hasLabel("book").count().next());
Assert.assertEquals(8L, g.V().hasLabel("book", "language")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("lived", "California")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", 61).count().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.has("age", P.gte(61)).count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(62)).count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(62))
.has("lived", "California")
.count().next());
Assert.assertEquals(0L, g.V().hasLabel("author")
.has("age", P.lt(62))
.has("lived", "Canadian")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(63))
.has("lived", "Canadian")
.count().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.has("age", P.lt(63))
.has("lived", P.within("California",
"Canadian"))
.count().next());
Assert.assertEquals(9L, g.V().hasLabel("person")
.has("age", 8)
.count().next());
Assert.assertEquals(50L, g.V().hasLabel("person")
.has("city", "Beijing")
.count().next());
Assert.assertEquals(5L, g.V().hasLabel("person")
.has("age", 8)
.has("city", "Beijing")
.count().next());
Assert.assertEquals(3L, g.V().hasLabel("person")
.has("age", 8)
.has("city", "Beijing")
.limit(3).count().next());
Assert.assertEquals(110L, g.V().count().min().next());
Assert.assertEquals(5L, g.V().hasLabel("book").count().max().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.values("age").count().next());
Assert.assertEquals(8L, g.V().hasLabel("author")
.values().count().next());
}
@Test
public void testQueryCountWithOptimizeByIndex() {
HugeGraph graph = graph();
graph.schema().indexLabel("authorByLived").onV("author")
.secondary().by("lived").create();
graph.schema().indexLabel("authorByAge").onV("author")
.range().by("age").create();
init10Vertices();
initPersonIndex(true);
init100Persons();
boolean old = Whitebox.getInternalState(params().graphTransaction(),
"optimizeAggrByIndex");
Whitebox.setInternalState(params().graphTransaction(),
"optimizeAggrByIndex", true);
try {
GraphTraversalSource g = graph.traversal();
Assert.assertEquals(110L, g.V().count().next());
Assert.assertEquals(2L, g.V().hasLabel("author").count().next());
Assert.assertEquals(3L, g.V().hasLabel("language").count().next());
Assert.assertEquals(5L, g.V().hasLabel("book").count().next());
Assert.assertEquals(8L, g.V().hasLabel("book", "language")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("lived", "California")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", 61).count().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.has("age", P.gte(61)).count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(62)).count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(62))
.has("lived", "California")
.count().next());
Assert.assertEquals(0L, g.V().hasLabel("author")
.has("age", P.lt(62))
.has("lived", "Canadian")
.count().next());
Assert.assertEquals(1L, g.V().hasLabel("author")
.has("age", P.lt(63))
.has("lived", "Canadian")
.count().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.has("age", P.lt(63))
.has("lived", P.within("California",
"Canadian"))
.count().next());
Assert.assertEquals(9L, g.V().hasLabel("person")
.has("age", 8)
.count().next());
Assert.assertEquals(50L, g.V().hasLabel("person")
.has("city", "Beijing")
.count().next());
Assert.assertEquals(5L, g.V().hasLabel("person")
.has("age", 8)
.has("city", "Beijing")
.count().next());
Assert.assertEquals(3L, g.V().hasLabel("person")
.has("age", 8)
.has("city", "Beijing")
.limit(3).count().next());
Assert.assertEquals(110L, g.V().count().min().next());
Assert.assertEquals(5L, g.V().hasLabel("book").count().max().next());
Assert.assertEquals(2L, g.V().hasLabel("author")
.values("age").count().next());
Assert.assertEquals(8L, g.V().hasLabel("author")
.values().count().next());
} finally {
Whitebox.setInternalState(params().graphTransaction(),
"optimizeAggrByIndex", old);
}
}
@Test
public void testAddVertexWithUniqueIndex() {
SchemaManager schema = graph().schema();
schema.vertexLabel("user")
.properties("name")
.create();
schema.indexLabel("userByName").onV("user").by("name").unique()
.create();
Vertex v = graph().addVertex(T.label, "user", "name", "Tom");
this.commitTx();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "user", "name", "Tom");
this.commitTx();
});
v.remove();
graph().addVertex(T.label, "user", "name", "Tom");
this.commitTx();
}
@Test
public void testAddVerticesWithUniqueIndexInTx() {
SchemaManager schema = graph().schema();
schema.vertexLabel("user")
.properties("name")
.create();
schema.indexLabel("userByName").onV("user").by("name").unique()
.create();
graph().addVertex(T.label, "user", "name", "Tom");
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "user", "name", "Tom");
this.commitTx();
});
}
@Test
public void testUpdatePropertyToValueOfRemovedVertexWithUniqueIndex() {
SchemaManager schema = graph().schema();
schema.vertexLabel("user")
.properties("name")
.create();
schema.indexLabel("userByName").onV("user").by("name").unique()
.create();
Vertex tom = graph().addVertex(T.label, "user", "name", "Tom");
Vertex jack = graph().addVertex(T.label, "user", "name", "Jack");
Vertex james = graph().addVertex(T.label, "user", "name", "James");
this.commitTx();
tom.remove();
this.commitTx();
jack.property("name", "Tom");
this.commitTx();
james.remove();
jack.property("name", "James");
this.commitTx();
}
@Test
public void testAddVerticesWithUniqueIndexForNullableProperties() {
SchemaManager schema = graph().schema();
schema.vertexLabel("user")
.properties("name", "city", "age")
.nullableKeys("name", "city", "age")
.create();
schema.indexLabel("userByNameCityAge")
.onV("user").by("name", "city", "age")
.unique().create();
graph().addVertex(T.label, "user", "name", "Tom",
"city", "Beijing", "age", 18);
this.commitTx();
// Nullable properties
graph().addVertex(T.label, "user", "name", "Tom", "city", "Beijing");
this.commitTx();
graph().addVertex(T.label, "user", "name", "Tom", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "city", "Beijing", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "name", "Tom");
this.commitTx();
graph().addVertex(T.label, "user", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "city", "Beijing");
this.commitTx();
graph().addVertex(T.label, "user");
this.commitTx();
// Empty String properties
graph().addVertex(T.label, "user", "name", "", "city", "", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "name", "", "city", "");
this.commitTx();
graph().addVertex(T.label, "user", "name", "", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "city", "", "age", 18);
this.commitTx();
graph().addVertex(T.label, "user", "name", "");
this.commitTx();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "user", "age", 18);
this.commitTx();
}, e -> {
String message = e.getMessage();
Assert.assertTrue(message.contains("Unique constraint " +
"userByNameCityAge"));
Assert.assertTrue(message.contains("conflict is found"));
});
graph().addVertex(T.label, "user", "city", "");
this.commitTx();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "user");
this.commitTx();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph().addVertex(T.label, "user", "city", "\u0001");
this.commitTx();
});
}
@Test
public void testQueryByUniqueIndex() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("node")
.properties("name")
.useAutomaticId()
.ifNotExist()
.create();
schema.indexLabel("nodeByName")
.unique()
.onV("node")
.by("name")
.ifNotExist()
.create();
graph.addVertex(T.label, "node", "name", "tom");
this.mayCommitTx();
Assert.assertThrows(NoIndexException.class, () -> {
graph.traversal().V().hasLabel("node").has("name", "tom").next();
}, (e) -> {
Assert.assertEquals("Don't accept query based on properties " +
"[name] that are not indexed in label 'node'," +
" may not match secondary condition",
e.getMessage());
});
}
@Test
public void testRemoveVertex() {
HugeGraph graph = graph();
init10Vertices();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(10, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
Vertex vertex = vertex("author", "id", 1);
vertex.remove();
this.mayCommitTx();
vertices = graph.traversal().V().toList();
Assert.assertEquals(9, vertices.size());
assertNotContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
}
@Test
public void testRemoveVertexById() {
HugeGraph graph = graph();
graph.schema().vertexLabel("author2")
.properties("id", "name", "age", "lived")
.primaryKeys("id")
.nullableKeys("age", "lived")
.enableLabelIndex(false)
.create();
graph.addVertex(T.label, "author2", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "Canadian");
graph.addVertex(T.label, "author", "id", 2,
"name", "Guido van Rossum", "age", 61,
"lived", "California");
this.mayCommitTx();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(2, vertices.size());
assertContains(vertices,
T.label, "author2", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
// remove vertex without label index
Vertex vertex = vertex("author2", "id", 1);
graph.removeVertex(vertex.label(), vertex.id());
this.mayCommitTx();
vertices = graph.traversal().V().toList();
Assert.assertEquals(1, vertices.size());
assertNotContains(vertices,
T.label, "author2", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
// remove vertex with label index
vertex = vertex("author", "id", 2);
graph.removeVertex(vertex.label(), vertex.id());
this.mayCommitTx();
vertices = graph.traversal().V().toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testRemoveVertexOfNotExists() {
HugeGraph graph = graph();
init10Vertices();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(10, vertices.size());
assertContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
Vertex vertex = vertex("author", "id", 1);
vertex.remove();
this.mayCommitTx();
vertices = graph.traversal().V().toList();
Assert.assertEquals(9, vertices.size());
assertNotContains(vertices,
T.label, "author", "id", 1, "name", "James Gosling",
"age", 62, "lived", "Canadian");
// Remove again
vertex.remove();
this.mayCommitTx();
}
@Test
public void testRemoveVertexAfterAddVertexWithTx() {
HugeGraph graph = graph();
GraphTransaction tx = params().openTransaction();
Vertex java1 = tx.addVertex(T.label, "book", "name", "java-1");
tx.addVertex(T.label, "book", "name", "java-2");
tx.commit();
java1.remove();
tx.commit();
tx.close();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(1, vertices.size());
assertNotContains(vertices, T.label, "book", "name", "java-1");
}
@Test
public void testRemoveVertexOneByOne() {
HugeGraph graph = graph();
init10Vertices();
List<Vertex> vertices = graph.traversal().V().toList();
Assert.assertEquals(10, vertices.size());
for (int i = 0; i < vertices.size(); i++) {
vertices.get(i).remove();
this.mayCommitTx();
Assert.assertEquals(9 - i, graph.traversal().V().toList().size());
}
}
@Test
public void testAddVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom");
this.mayCommitTx();
// Add properties
vertex.property("name", "Tom2");
vertex.property("age", 10);
vertex.property("lived", "USA");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Tom2", vertex.property("name").value());
Assert.assertEquals(10, vertex.property("age").value());
Assert.assertEquals("USA", vertex.property("lived").value());
}
@Test
public void testAddVertexPropertyExisted() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Tom", vertex.property("name").value());
vertex.property("name", "Tom2");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Tom2", vertex.property("name").value());
}
@Test
public void testAddVertexPropertyExistedWithIndex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "person", "name", "Tom",
"city", "Hongkong", "age", 3);
this.mayCommitTx();
vertex = vertex("person", "name", "Tom");
Assert.assertEquals(3, vertex.property("age").value());
vertex.property("age", 4);
this.mayCommitTx();
Assert.assertEquals(4, vertex.property("age").value());
vertex = vertex("person", "name", "Tom");
Assert.assertEquals(4, vertex.property("age").value());
}
@Test
public void testAddVertexPropertyNotInVertexLabel() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom");
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("time", "2017-1-1");
});
}
@Test
public void testAddVertexPropertyWithNotExistPropKey() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Jim");
this.mayCommitTx();
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("prop-not-exist", "2017-1-1");
});
}
@Test
public void testAddVertexPropertyOfPrimaryKey() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Jim");
this.mayCommitTx();
Assert.assertEquals(1, vertex.property("id").value());
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Update primary key property
vertex.property("id", 2);
});
}
@Test
public void testAddVertexPropertyWithSpecialValueForSecondaryIndex() {
HugeGraph graph = graph();
initPersonIndex(true);
graph.addVertex(T.label, "person", "name", "1",
"city", "b\u0001", "age", 1);
graph.addVertex(T.label, "person", "name", "2",
"city", "c\u0002", "age", 2);
graph.addVertex(T.label, "person", "name", "3",
"city", "d\u0003", "age", 3);
this.mayCommitTx();
List<Vertex> vertices;
vertices = graph.traversal().V().has("city", "b\u0001").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("1", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("city", "c\u0002").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("2", vertices.get(0).value("name"));
vertices = graph.traversal().V().has("city", "d\u0003").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("3", vertices.get(0).value("name"));
String backend = graph.backend();
Set<String> nonZeroBackends = ImmutableSet.of("postgresql",
"rocksdb", "hbase");
if (nonZeroBackends.contains(backend)) {
Assert.assertThrows(Exception.class, () -> {
graph.addVertex(T.label, "person", "name", "0",
"city", "a\u0000", "age", 0);
this.commitTx();
}, e -> {
if (e instanceof BackendException) {
Assert.assertContains("0x00", e.getCause().getMessage());
} else {
Assert.assertContains("0x00", e.getMessage());
}
});
} else {
graph.addVertex(T.label, "person", "name", "0",
"city", "a\u0000", "age", 0);
this.commitTx();
vertices = graph.traversal().V().has("city", "a\u0000").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("0", vertices.get(0).value("name"));
}
}
@Test
public void testAddVertexPropertyWithIllegalValueForSecondaryIndex() {
HugeGraph graph = graph();
initPersonIndex(true);
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "\u0000", "age", 3);
this.commitTx();
}, e -> {
Assert.assertContains("Illegal leading char '\\u0' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "\u0001", "age", 3);
this.commitTx();
}, e -> {
Assert.assertContains("Illegal leading char '\\u1' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "\u0002", "age", 3);
this.commitTx();
}, e -> {
Assert.assertContains("Illegal leading char '\\u2' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name", "Baby",
"city", "\u0003", "age", 3);
this.commitTx();
}, e -> {
Assert.assertContains("Illegal leading char '\\u3' in index",
e.getMessage());
});
}
@Test
public void testAddVertexMultiTimesWithMergedProperties() {
Assume.assumeTrue("Not support merge vertex property",
storeFeatures().supportsMergeVertexProperty());
HugeGraph graph = graph();
// "city" is a non-nullable property
graph.addVertex(T.label, "person", "name", "marko", "city", "Beijing",
"birth", "1992-11-17 12:00:00.000");
this.commitTx();
Vertex vertex = vertex("person", "name", "marko");
Assert.assertEquals("Beijing", vertex.value("city"));
Assert.assertEquals(Utils.date("1992-11-17 12:00:00.000"),
vertex.value("birth"));
Assert.assertFalse(vertex.property("age").isPresent());
// append property 'age'
graph.addVertex(T.label, "person", "name", "marko", "city", "Beijing",
"age", 26);
this.commitTx();
Assert.assertEquals("Beijing", vertex.value("city"));
vertex = vertex("person", "name", "marko");
Assert.assertEquals(26, (int) vertex.value("age"));
Assert.assertEquals(Utils.date("1992-11-17 12:00:00.000"),
vertex.value("birth"));
// update property "birth" and keep the original properties unchanged
graph.addVertex(T.label, "person", "name", "marko", "city", "Beijing",
"birth", "1993-11-17 12:00:00.000");
this.commitTx();
vertex = vertex("person", "name", "marko");
Assert.assertEquals("Beijing", vertex.value("city"));
Assert.assertEquals(26, (int) vertex.value("age"));
Assert.assertEquals(Utils.date("1993-11-17 12:00:00.000"),
vertex.value("birth"));
}
@Test
public void testRemoveVertexProperty() {
HugeGraph graph = graph();
Vertex v = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "age", 10, "lived", "USA");
this.mayCommitTx();
// Remove "name" property
Assert.assertTrue(v.property("name").isPresent());
Assert.assertTrue(v.property("lived").isPresent());
Assert.assertThrows(IllegalArgumentException.class, () -> {
v.property("name").remove();
this.commitTx();
});
Assert.assertTrue(v.property("name").isPresent());
Assert.assertTrue(v.property("lived").isPresent());
// Remove "lived" property
Vertex vertex = vertex("author", "id", 1);
Assert.assertTrue(vertex.property("name").isPresent());
Assert.assertTrue(vertex.property("lived").isPresent());
vertex.property("lived").remove();
this.mayCommitTx();
Assert.assertTrue(vertex.property("name").isPresent());
Assert.assertFalse(vertex.property("lived").isPresent());
vertex = vertex("author", "id", 1);
Assert.assertEquals(10, vertex.property("age").value());
Assert.assertTrue(vertex.property("name").isPresent());
Assert.assertFalse(vertex.property("lived").isPresent());
}
@Test
public void testRemoveVertexPropertyOfPrimaryKey() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "age", 10,
"lived", "USA");
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("id").remove();
});
}
@Test
public void testRemoveVertexPropertyNullableWithIndex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
vertex.property("age").remove();
}
@Test
public void testRemoveVertexPropertyNonNullWithIndex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("name").remove();
});
}
@Test
public void testRemoveVertexPropertyNullableWithoutIndex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Baby", "lived", "Hongkong");
vertex.property("age").remove();
}
@Test
public void testRemoveVertexPropertyNonNullWithoutIndex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Baby", "lived", "Hongkong");
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("name").remove();
});
}
@Test
public void testQueryVertexByPropertyWithEmptyString() {
HugeGraph graph = graph();
initPersonIndex(true);
graph.addVertex(T.label, "person", "name", "Baby", "city", "");
this.commitTx();
Vertex vertex = graph.traversal().V().has("city", "").next();
Assert.assertEquals("Baby", vertex.value("name"));
Assert.assertEquals("", vertex.value("city"));
}
@Test
public void testQueryVertexBeforeAfterUpdateMultiPropertyWithIndex() {
HugeGraph graph = graph();
initPersonIndex(true);
Vertex vertex = graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
this.commitTx();
List<Vertex> vl = graph.traversal().V().has("age", 3).toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
vl = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
vl = graph.traversal().V().has("age", 5).toList();
Assert.assertEquals(0, vl.size());
vl = graph.traversal().V().has("city", "Shanghai").toList();
Assert.assertEquals(0, vl.size());
vertex.property("age", 5);
vertex.property("city", "Shanghai");
this.commitTx();
vl = graph.traversal().V().has("age", 3).toList();
Assert.assertEquals(0, vl.size());
vl = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(0, vl.size());
vl = graph.traversal().V().has("age", 5).toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
vl = graph.traversal().V().has("city", "Shanghai").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
}
@Test
public void testQueryVertexBeforeAfterUpdatePropertyWithSecondaryIndex() {
HugeGraph graph = graph();
initPersonIndex(true);
Vertex vertex = graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
this.commitTx();
List<Vertex> vl = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
vl = graph.traversal().V().has("city", "Shanghai").toList();
Assert.assertEquals(0, vl.size());
vertex.property("city", "Shanghai");
this.commitTx();
vl = graph.traversal().V().has("city", "Hongkong").toList();
Assert.assertEquals(0, vl.size());
vl = graph.traversal().V().has("city", "Shanghai").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
}
@Test
public void testQueryVertexBeforeAfterUpdatePropertyWithRangeIndex() {
HugeGraph graph = graph();
initPersonIndex(false);
Vertex vertex = graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3);
this.commitTx();
List<Vertex> vl = graph.traversal().V().has("age", 3).toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
vl = graph.traversal().V().has("age", 5).toList();
Assert.assertEquals(0, vl.size());
vertex.property("age", 5);
this.commitTx();
vl = graph.traversal().V().has("age", 3).toList();
Assert.assertEquals(0, vl.size());
vl = graph.traversal().V().has("age", 5).toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("Baby", vl.get(0).value("name"));
}
@Test
public void testQueryVertexWithNullablePropertyInCompositeIndex() {
HugeGraph graph = graph();
initComputerIndex();
graph.addVertex(T.label, "computer", "name", "1st", "band", "10Gbps",
"cpu", "2GHz", "ram", "8GB", "price", 1000);
this.commitTx();
List<Vertex> vl = graph.traversal().V().has("cpu", "2GHz").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("1st", vl.get(0).value("name"));
vl = graph.traversal().V().has("cpu", "2GHz")
.has("ram", "8GB").toList();
Assert.assertEquals(1, vl.size());
Assert.assertEquals("1st", vl.get(0).value("name"));
}
@Test
public void testUpdateVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.mayCommitTx();
vertex.property("lived").remove();
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testUpdateVertexPropertyTwice() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.mayCommitTx();
vertex.property("lived").remove();
vertex.property("lived").remove();
vertex.property("lived", "Hangzhou");
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testUpdateVertexPropertyOfNewVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testUpdateVertexPropertyOfPrimaryKey() {
HugeGraph graph = graph();
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.mayCommitTx();
Vertex vertex = vertex("author", "id", 1);
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Update primary key property
vertex.property("id", 2);
});
}
@Test
public void testUpdateVertexPropertyOfPrimaryKeyOfNewVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
Assert.assertThrows(IllegalArgumentException.class, () -> {
// Update primary key property
vertex.property("id", 2);
});
}
@Test
public void testUpdateVertexPropertyOfAddingVertex() {
HugeGraph graph = graph();
Vertex vertex0 = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex0.property("lived").remove();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.commitTx();
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived").remove();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived", "Shanghai");
});
}
@Test
public void testUpdateVertexPropertyOfRemovingVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.commitTx();
vertex.remove();
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived").remove();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived", "Shanghai");
});
}
@Test
public void testUpdateVertexPropertyOfRemovingVertexWithDrop() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
this.commitTx();
graph.traversal().V(vertex.id()).drop().iterate();
// Update on dirty vertex
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived").remove();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
vertex.property("lived", "Shanghai");
});
}
@Test
public void testUpdateVertexPropertyOfAggregateType() {
Assume.assumeTrue("Not support aggregate property",
storeFeatures().supportsAggregateProperty());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("worstScore")
.asInt().valueSingle().calcMin()
.ifNotExist().create();
schema.propertyKey("bestScore")
.asInt().valueSingle().calcMax()
.ifNotExist().create();
schema.propertyKey("testNum")
.asInt().valueSingle().calcSum()
.ifNotExist().create();
schema.propertyKey("rank")
.asInt().valueSet().calcSet()
.ifNotExist().create();
schema.propertyKey("reword")
.asInt().valueList().calcList()
.ifNotExist().create();
schema.vertexLabel("student")
.properties("name", "worstScore", "bestScore",
"testNum", "rank", "reword")
.primaryKeys("name")
.nullableKeys("worstScore", "bestScore",
"testNum", "rank", "reword")
.ifNotExist()
.create();
graph.addVertex(T.label, "student", "name", "Tom", "worstScore", 55,
"bestScore", 96, "testNum", 1, "rank", 8, "reword", 8);
this.commitTx();
Vertex tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(55, tom.value("worstScore"));
Assert.assertEquals(96, tom.value("bestScore"));
Assert.assertEquals(1, tom.value("testNum"));
Assert.assertEquals(ImmutableSet.of(8), tom.value("rank"));
Assert.assertEquals(ImmutableList.of(8), tom.value("reword"));
tom.property("worstScore", 45);
tom.property("bestScore", 98);
tom.property("testNum", 1);
tom.property("rank", 12);
tom.property("reword", 12);
this.commitTx();
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(98, tom.value("bestScore"));
Assert.assertEquals(2, tom.value("testNum"));
Assert.assertEquals(ImmutableSet.of(8, 12), tom.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12), tom.value("reword"));
tom.property("worstScore", 65);
tom.property("bestScore", 99);
tom.property("testNum", 1);
tom.property("rank", 8);
tom.property("reword", 8);
this.commitTx();
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(99, tom.value("bestScore"));
Assert.assertEquals(3, tom.value("testNum"));
Assert.assertEquals(ImmutableSet.of(8, 12), tom.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12, 8),
tom.value("reword"));
tom.property("worstScore", 75);
tom.property("bestScore", 100);
tom.property("testNum", 1);
tom.property("rank", 1);
tom.property("reword", 1);
this.commitTx();
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(100, tom.value("bestScore"));
Assert.assertEquals(4, tom.value("testNum"));
Assert.assertEquals(ImmutableSet.of(1, 8, 12),
tom.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12, 8, 1),
tom.value("reword"));
}
@Test
public void testAddAndUpdateVertexPropertyOfAggregateType() {
Assume.assumeTrue("Not support aggregate property",
storeFeatures().supportsAggregateProperty());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("worstScore")
.asInt().valueSingle().calcMin()
.ifNotExist().create();
schema.propertyKey("bestScore")
.asInt().valueSingle().calcMax()
.ifNotExist().create();
schema.propertyKey("testNum")
.asInt().valueSingle().calcSum()
.ifNotExist().create();
schema.propertyKey("rank")
.asInt().valueSet().calcSet()
.ifNotExist().create();
schema.propertyKey("reword")
.asInt().valueList().calcList()
.ifNotExist().create();
schema.vertexLabel("student")
.properties("name", "worstScore", "bestScore",
"testNum", "rank", "reword")
.primaryKeys("name")
.nullableKeys("worstScore", "bestScore",
"testNum", "rank", "reword")
.ifNotExist()
.create();
Vertex tom = graph.addVertex(T.label, "student", "name", "Tom",
"worstScore", 55, "bestScore", 96,
"testNum", 1, "rank", 8, "reword", 8);
tom.property("worstScore", 65);
tom.property("bestScore", 94);
tom.property("testNum", 2);
tom.property("rank", 12);
tom.property("reword", 12);
Vertex result = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(65, result.value("worstScore"));
Assert.assertEquals(94, result.value("bestScore"));
Assert.assertEquals(2, result.value("testNum"));
Assert.assertEquals(ImmutableSet.of(8, 12), result.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12), result.value("reword"));
this.commitTx();
result = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(65, result.value("worstScore"));
Assert.assertEquals(94, result.value("bestScore"));
Assert.assertEquals(2, result.value("testNum"));
Assert.assertEquals(ImmutableSet.of(8, 12), result.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12), result.value("reword"));
tom = graph.addVertex(T.label, "student", "name", "Tom",
"worstScore", 55, "bestScore", 96,
"testNum", 1, "rank", 2, "reword", 2);
tom.property("worstScore", 75);
tom.property("bestScore", 92);
tom.property("testNum", 2);
tom.property("rank", 1);
tom.property("reword", 1);
Assert.assertEquals(75, tom.value("worstScore"));
Assert.assertEquals(92, tom.value("bestScore"));
Assert.assertEquals(2, tom.value("testNum"));
Assert.assertEquals(ImmutableSet.of(1, 2),
tom.value("rank"));
Assert.assertEquals(ImmutableList.of(2, 1),
tom.value("reword"));
Assert.assertEquals(75, tom.property("worstScore").value());
Assert.assertEquals(92, tom.property("bestScore").value());
Assert.assertEquals(2, tom.property("testNum").value());
Assert.assertEquals(ImmutableSet.of(1, 2),
tom.property("rank").value());
Assert.assertEquals(ImmutableList.of(2, 1),
tom.value("reword"));
this.commitTx();
result = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(65, result.value("worstScore"));
Assert.assertEquals(94, result.value("bestScore"));
Assert.assertEquals(4, result.value("testNum"));
Assert.assertEquals(ImmutableSet.of(1, 2, 8, 12),
result.value("rank"));
Assert.assertEquals(ImmutableList.of(8, 12, 2, 1),
result.value("reword"));
}
@Test
public void testQueryVertexByAggregateProperty() {
Assume.assumeTrue("Not support aggregate property",
storeFeatures().supportsAggregateProperty());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("worstScore")
.asInt().valueSingle().calcMin()
.ifNotExist().create();
schema.propertyKey("bestScore")
.asInt().valueSingle().calcMax()
.ifNotExist().create();
schema.propertyKey("testNum")
.asInt().valueSingle().calcSum()
.ifNotExist().create();
schema.propertyKey("no")
.asText().valueSingle().calcOld()
.ifNotExist().create();
schema.propertyKey("rank")
.asInt().valueSet().calcSet()
.ifNotExist().create();
schema.propertyKey("reword")
.asInt().valueList().calcList()
.ifNotExist().create();
schema.vertexLabel("student")
.properties("name", "worstScore", "bestScore",
"testNum", "no", "rank", "reword")
.primaryKeys("name")
.nullableKeys("worstScore", "bestScore",
"testNum", "no", "rank", "reword")
.ifNotExist()
.create();
schema.indexLabel("studentByWorstScore")
.onV("student").by("worstScore").range().ifNotExist().create();
schema.indexLabel("studentByBestScore")
.onV("student").by("bestScore").range().ifNotExist().create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
schema.indexLabel("studentByTestNum")
.onV("student").by("testNum").range().ifNotExist().create();
}, e -> {
Assert.assertContains("The aggregate type SUM is not indexable",
e.getMessage());
});
schema.indexLabel("studentByNo")
.onV("student").by("no").secondary().ifNotExist().create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
schema.indexLabel("studentByRank")
.onV("student").by("rank").secondary().ifNotExist().create();
}, e -> {
Assert.assertTrue(e.getMessage(), e.getMessage().contains(
"The aggregate type SET is not indexable"));
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
schema.indexLabel("studentByReword")
.onV("student").by("reword").secondary().ifNotExist()
.create();
}, e -> {
Assert.assertTrue(e.getMessage(), e.getMessage().contains(
"The aggregate type LIST is not indexable"));
});
graph.addVertex(T.label, "student", "name", "Tom", "worstScore", 55,
"bestScore", 96, "testNum", 1, "no", "001");
this.commitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
Vertex tom = vertices.get(0);
Assert.assertEquals(55, tom.value("worstScore"));
Assert.assertEquals(96, tom.value("bestScore"));
Assert.assertEquals(1, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
List<Vertex> results = graph.traversal().V()
.has("worstScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", P.lt(60)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", 55).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.lt(100)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", 96).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("no", "001").toList();
Assert.assertEquals(vertices, results);
tom.property("worstScore", 45);
tom.property("bestScore", 98);
tom.property("testNum", 1);
tom.property("no", "002");
this.commitTx();
vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
tom = vertices.get(0);
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(98, tom.value("bestScore"));
Assert.assertEquals(2, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
results = graph.traversal().V().has("worstScore", P.gt(30)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", P.lt(60)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", 45).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.lt(100)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", 98).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("no", "001").toList();
Assert.assertEquals(vertices, results);
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
tom.property("worstScore", 65);
tom.property("bestScore", 99);
tom.property("testNum", 1);
tom.property("no", "003");
this.commitTx();
vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
tom = vertices.get(0);
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(99, tom.value("bestScore"));
Assert.assertEquals(3, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
results = graph.traversal().V().has("worstScore", P.gt(30)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", P.lt(60)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", 45).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.lt(100)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", 99).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("no", "001").toList();
Assert.assertEquals(vertices, results);
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
tom.property("worstScore", 75);
tom.property("bestScore", 100);
tom.property("testNum", 1);
tom.property("no", "004");
this.commitTx();
vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
tom = vertices.get(0);
Assert.assertEquals(45, tom.value("worstScore"));
Assert.assertEquals(100, tom.value("bestScore"));
Assert.assertEquals(4, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
results = graph.traversal().V().has("worstScore", P.gt(30)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", P.lt(60)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", 45).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.lt(101)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", 100).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("no", "001").toList();
Assert.assertEquals(vertices, results);
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
tom.property("worstScore", 35);
tom.property("bestScore", 99);
tom.property("testNum", 1);
tom.property("no", "005");
this.commitTx();
tom.property("worstScore", 65);
tom.property("bestScore", 93);
tom.property("testNum", 1);
tom.property("no", "006");
this.commitTx();
tom.property("worstScore", 58);
tom.property("bestScore", 63);
tom.property("testNum", 1);
tom.property("no", "007");
this.commitTx();
vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
tom = vertices.get(0);
Assert.assertEquals(35, tom.value("worstScore"));
Assert.assertEquals(100, tom.value("bestScore"));
Assert.assertEquals(7, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
results = graph.traversal().V().has("worstScore", P.gt(30)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", P.lt(60)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("worstScore", 35).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.gt(50)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", P.lt(101)).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("bestScore", 100).toList();
Assert.assertEquals(vertices, results);
results = graph.traversal().V().has("no", "001").toList();
Assert.assertEquals(vertices, results);
}
@Test
public void testUpdateVertexWithAggregatePropertyMultiTimes() {
Assume.assumeTrue("Not support aggregate property",
storeFeatures().supportsAggregateProperty());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.propertyKey("worstScore")
.asInt().valueSingle().calcMin()
.ifNotExist().create();
schema.propertyKey("bestScore")
.asInt().valueSingle().calcMax()
.ifNotExist().create();
schema.propertyKey("testNum")
.asInt().valueSingle().calcSum()
.ifNotExist().create();
schema.propertyKey("no")
.asText().valueSingle().calcOld()
.ifNotExist().create();
schema.propertyKey("rank")
.asInt().valueSet().calcSet()
.ifNotExist().create();
schema.propertyKey("reword")
.asInt().valueList().calcList()
.ifNotExist().create();
schema.vertexLabel("student")
.properties("name", "worstScore", "bestScore",
"testNum", "no", "rank", "reword")
.primaryKeys("name")
.nullableKeys("worstScore", "bestScore",
"testNum", "no", "rank", "reword")
.ifNotExist()
.create();
schema.indexLabel("studentByWorstScore")
.onV("student").by("worstScore").range().ifNotExist().create();
schema.indexLabel("studentByBestScore")
.onV("student").by("bestScore").range().ifNotExist().create();
Assert.assertThrows(IllegalArgumentException.class, () -> {
schema.indexLabel("studentByTestNum")
.onV("student").by("testNum").range().ifNotExist().create();
}, e -> {
Assert.assertContains("The aggregate type SUM is not indexable",
e.getMessage());
});
schema.indexLabel("studentByNo")
.onV("student").by("no").secondary().ifNotExist().create();
graph.addVertex(T.label, "student", "name", "Tom", "worstScore", 55,
"bestScore", 96, "testNum", 1, "no", "001",
"rank", 1, "reword", 1);
this.commitTx();
List<Vertex> vertices = graph.traversal().V().hasLabel("student")
.has("name", "Tom").toList();
Assert.assertEquals(1, vertices.size());
Vertex tom = vertices.get(0);
Assert.assertEquals(55, tom.value("worstScore"));
Assert.assertEquals(96, tom.value("bestScore"));
Assert.assertEquals(1, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
Assert.assertEquals(ImmutableSet.of(1), tom.value("rank"));
Assert.assertEquals(ImmutableList.of(1), tom.value("reword"));
Set<Integer> ranks = new HashSet<>();
List<Integer> rewords = new ArrayList<>();
int rank;
int reword;
ranks.add(1);
rewords.add(1);
Random random = new Random();
for (int i = 0; i < 100; i++) {
tom.property("worstScore", 65);
tom.property("bestScore", 94);
tom.property("testNum", 1);
tom.property("no", "002");
rank = random.nextInt();
ranks.add(rank);
tom.property("rank", rank);
reword = random.nextInt();
rewords.add(reword);
tom.property("reword", reword);
this.commitTx();
tom = graph.traversal().V().hasLabel("student")
.has("name", "Tom").next();
Assert.assertEquals(55, tom.value("worstScore"));
Assert.assertEquals(96, tom.value("bestScore"));
Assert.assertEquals(i + 2, tom.value("testNum"));
Assert.assertEquals("001", tom.value("no"));
Assert.assertEquals(ranks, tom.value("rank"));
Assert.assertEquals(rewords, tom.value("reword"));
}
}
// Insert -> {Insert, Delete, Append, Eliminate}
@Test
public void testInsertAndInsertVertex() {
HugeGraph graph = graph();
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Shanghai");
this.mayCommitTx();
Vertex vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testInsertAndDeleteVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.remove();
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
@Test
public void testInsertAndAppendVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testInsertAndEliminateVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("lived").isPresent());
}
// Delete -> {Insert, Delete, Append, Eliminate}
@Test
public void testDeleteAndInsertVertex() {
HugeGraph graph = graph();
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
graph.traversal().V().hasLabel("author").has("id", 1).next().remove();
graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Shanghai");
this.mayCommitTx();
Vertex vertex = vertex("author", "id", 1);
Assert.assertTrue(vertex.property("lived").isPresent());
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testDeleteAndDeleteVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.remove();
vertex.remove();
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
@Test
public void testDeleteAndAppendVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.remove();
vertex.property("lived", "Shanghai");
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
@Test
public void testDeleteAndEliminateVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.remove();
vertex.property("lived").remove();
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
// Append -> {Insert, Delete, Append, Eliminate}
@Test
public void testAppendAndInsertVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived", "Wuhan");
graph.addVertex(T.label, "author", "id", 1, "name", "Tom",
"lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertTrue(vertex.property("lived").isPresent());
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testAppendAndDeleteVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived", "Wuhan");
vertex.remove();
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
@Test
public void testAppendAndAppendSameVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived", "Wuhan");
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testAppendAndAppendDifferentVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("name", "Tomcat");
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertEquals("Tomcat", vertex.property("name").value());
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testAppendAndEliminateSameVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived", "Shanghai");
vertex.property("lived").remove();
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("lived").isPresent());
}
@Test
public void testAppendAndEliminateDifferentVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("name", "Tomcat");
vertex.property("lived").remove();
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("lived").isPresent());
Assert.assertEquals("Tomcat", vertex.property("name").value());
}
// Eliminate -> {Insert, Delete, Append, Eliminate}
@Test
public void testEliminateAndInsertVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
graph.addVertex(T.label, "author", "id", 1, "name", "Tom",
"lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertTrue(vertex.property("lived").isPresent());
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testEliminateAndDeleteVertex() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
vertex.remove();
this.mayCommitTx();
Assert.assertNull(vertex("author", "id", 1));
}
@Test
public void testEliminateAndAppendSameVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
vertex.property("lived", "Shanghai");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertTrue(vertex.property("lived").isPresent());
Assert.assertEquals("Shanghai", vertex.property("lived").value());
}
@Test
public void testEliminateAndAppendDifferentVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
vertex.property("name", "Tomcat");
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("lived").isPresent());
Assert.assertEquals("Tomcat", vertex.property("name").value());
}
@Test
public void testEliminateAndEliminateSameVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1,
"name", "Tom", "lived", "Beijing");
vertex.property("lived").remove();
vertex.property("lived").remove();
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("lived").isPresent());
}
@Test
public void testEliminateAndEliminateDifferentVertexProperty() {
HugeGraph graph = graph();
Vertex vertex = graph.addVertex(T.label, "author", "id", 1, "age", 18,
"name", "Tom", "lived", "Beijing");
vertex.property("age").remove();
vertex.property("lived").remove();
this.mayCommitTx();
vertex = vertex("author", "id", 1);
Assert.assertFalse(vertex.property("age").isPresent());
Assert.assertFalse(vertex.property("lived").isPresent());
}
@Test
public void testOverrideVertex() {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "marko",
"age", 18, "city", "Beijing");
this.mayCommitTx();
Vertex vertex = vertex("person", "name", "marko");
Assert.assertTrue(vertex.property("age").isPresent());
Assert.assertEquals(18, vertex.value("age"));
Assert.assertTrue(vertex.property("city").isPresent());
Assert.assertEquals("Beijing", vertex.value("city"));
graph.addVertex(T.label, "person", "name", "marko", "city", "Wuhan");
this.mayCommitTx();
vertex = vertex("person", "name", "marko");
Assert.assertFalse(vertex.property("age").isPresent());
Assert.assertTrue(vertex.property("city").isPresent());
Assert.assertEquals("Wuhan", vertex.value("city"));
graph.addVertex(T.label, "person", "name", "marko",
"age", 19, "city", "Shanghai");
this.mayCommitTx();
vertex = vertex("person", "name", "marko");
Assert.assertTrue(vertex.property("age").isPresent());
Assert.assertEquals(19, vertex.value("age"));
Assert.assertTrue(vertex.property("city").isPresent());
Assert.assertEquals("Shanghai", vertex.value("city"));
}
@Test
public void testScanVertex() {
HugeGraph graph = graph();
// TODO: also support test scan by range
Assume.assumeTrue("Not support scan",
storeFeatures().supportsScanToken() ||
storeFeatures().supportsScanKeyRange());
this.init10VerticesAndCommit();
List<Vertex> vertices = new LinkedList<>();
long splitSize = 1 * 1024 * 1024;
List<Shard> splits = graph.metadata(HugeType.VERTEX, "splits",
splitSize);
for (Shard split : splits) {
ConditionQuery q = new ConditionQuery(HugeType.VERTEX);
q.scan(split.start(), split.end());
vertices.addAll(ImmutableList.copyOf(graph.vertices(q)));
}
Assert.assertEquals(10, vertices.size());
}
@Test
public void testScanVertexInPaging() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support scan",
storeFeatures().supportsScanToken() ||
storeFeatures().supportsScanKeyRange());
this.init10VerticesAndCommit();
List<Vertex> vertices = new LinkedList<>();
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
String backend = graph.backend();
if (backend.equals("cassandra") || backend.equals("scylladb")) {
query.scan(String.valueOf(Long.MIN_VALUE),
String.valueOf(Long.MAX_VALUE));
} else {
query.scan(BackendTable.ShardSplitter.START,
BackendTable.ShardSplitter.END);
}
query.limit(1);
String page = PageInfo.PAGE_NONE;
while (page != null) {
query.page(page);
Iterator<Vertex> iterator = graph.vertices(query);
while (iterator.hasNext()) {
Vertex vertex = iterator.next();
Assert.assertTrue(query.test((HugeElement) vertex));
vertices.add(vertex);
}
page = PageInfo.pageInfo(iterator);
CloseableIterator.closeIterator(iterator);
}
Assert.assertEquals(10, vertices.size());
}
@Test
public void testScanVertexWithSplitSizeLt1MB() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support scan",
storeFeatures().supportsScanToken() ||
storeFeatures().supportsScanKeyRange());
init10Vertices();
long splitSize = 1 * 1024 * 1024 - 1;
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.metadata(HugeType.VERTEX, "splits", splitSize);
});
}
@Test
public void testScanVertexWithSplitSizeTypeError() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support scan",
storeFeatures().supportsScanToken() ||
storeFeatures().supportsScanKeyRange());
init10Vertices();
String splitSize = "123456";
Assert.assertThrows(ClassCastException.class, () -> {
graph.metadata(HugeType.VERTEX, "splits", splitSize);
});
}
@Test
public void testScanVertexWithoutSplitSize() {
HugeGraph graph = graph();
Assume.assumeTrue("Not support scan",
storeFeatures().supportsScanToken() ||
storeFeatures().supportsScanKeyRange());
init10Vertices();
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.metadata(HugeType.VERTEX, "splits");
});
long splitSize = 1 * 1024 * 1024;
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.metadata(HugeType.VERTEX, "splits", splitSize, "invalid-arg");
});
}
@Test
public void testQuerySingleIndexedPropertyByEqual() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("band", "lenovo").toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V().has("band", "apple").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQuerySingleIndexedPropertyByNotEqual() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("band", "acer").toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().has("band", "Hp").toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByEqualOnePrefix() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "3.2GHz").toList();
Assert.assertEquals(3, vertices.size());
vertices = graph.traversal().V().has("cpu", "4.6GHz").toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByNotEqualOnePrefix() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "2.8GHz").toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V().has("cpu", "4.8GHz").toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByEqualTwoPrefix() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "3.2GHz")
.has("ram", "16GB")
.toList();
Assert.assertEquals(2, vertices.size());
vertices = graph.traversal().V()
.has("ram", "32GB")
.has("cpu", "4.6GHz")
.toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByNotEqualTwoPrefix() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "3.3GHz")
.has("ram", "16GB")
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.has("ram", "32GB")
.has("cpu", "4.8GHz")
.toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByEqualAll() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "3.2GHz")
.has("band", "lenovo")
.has("ram", "16GB")
.toList();
Assert.assertEquals(1, vertices.size());
vertices = graph.traversal().V()
.has("ram", "32GB")
.has("cpu", "4.6GHz")
.has("band", "microsoft")
.toList();
Assert.assertEquals(1, vertices.size());
}
@Test
public void testQueryComplexIndexedPropertyByNotEqualAll() {
HugeGraph graph = graph();
init5Computers();
List<Vertex> vertices = graph.traversal().V()
.has("cpu", "3.3GHz")
.has("band", "apple")
.has("ram", "16GB")
.toList();
Assert.assertEquals(0, vertices.size());
vertices = graph.traversal().V()
.has("ram", "32GB")
.has("cpu", "4.8GHz")
.has("band", "microsoft")
.toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
init100Books();
GraphTraversal<Vertex, Vertex> iter = graph.traversal().V()
.has("~page", "").limit(10);
Assert.assertEquals(10, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
CloseableIterator.closeIterator(iter);
List<Vertex> vertices;
vertices = graph.traversal().V()
.has("~page", page).limit(1)
.toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = graph.traversal().V()
.has("~page", page).limit(33)
.toList();
Assert.assertEquals(33, vertices.size());
Vertex vertex2 = vertices.get(0);
Assert.assertEquals(vertex1.id(), vertex2.id());
Assert.assertEquals(vertex1.label(), vertex2.label());
Assert.assertEquals(IteratorUtils.asList(vertex1.properties()),
IteratorUtils.asList(vertex2.properties()));
vertices = graph.traversal().V()
.has("~page", page).limit(89)
.toList();
Assert.assertEquals(89, vertices.size());
Vertex vertex3 = vertices.get(88);
vertices = graph.traversal().V()
.has("~page", page).limit(90)
.toList();
Assert.assertEquals(90, vertices.size());
Vertex vertex4 = vertices.get(88);
Assert.assertEquals(vertex3.id(), vertex4.id());
Assert.assertEquals(vertex3.label(), vertex4.label());
Assert.assertEquals(IteratorUtils.asList(vertex3.properties()),
IteratorUtils.asList(vertex4.properties()));
vertices = graph.traversal().V()
.has("~page", page).limit(91)
.toList();
Assert.assertEquals(90, vertices.size());
}
@Test
public void testQueryByPageResultsMatchedAll() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
init100Books();
List<Vertex> all = graph.traversal().V().toList();
GraphTraversal<Vertex, Vertex> iter;
String page = PageInfo.PAGE_NONE;
int size = 22;
Set<Vertex> pageAll = new HashSet<>();
for (int i = 0; i < 100 / size; i++) {
iter = graph.traversal().V()
.has("~page", page).limit(size);
@SuppressWarnings("unchecked")
List<Vertex> vertices = IteratorUtils.asList(iter);
Assert.assertEquals(size, vertices.size());
pageAll.addAll(vertices);
page = TraversalUtil.page(iter);
CloseableIterator.closeIterator(iter);
}
iter = graph.traversal().V()
.has("~page", page).limit(size);
@SuppressWarnings("unchecked")
List<Vertex> vertices = IteratorUtils.asList(iter);
Assert.assertEquals(12, vertices.size());
pageAll.addAll(vertices);
page = TraversalUtil.page(iter);
Assert.assertEquals(100, pageAll.size());
Assert.assertTrue(all.containsAll(pageAll));
Assert.assertNull(page);
}
@Test
public void testQueryByPageResultsMatchedAllWithFullPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
init100Books();
List<Vertex> all = graph.traversal().V().toList();
GraphTraversal<Vertex, Vertex> iter;
String page = PageInfo.PAGE_NONE;
int size = 20;
Set<Vertex> pageAll = new HashSet<>();
for (int i = 0; i < 100 / size; i++) {
iter = graph.traversal().V()
.has("~page", page).limit(size);
@SuppressWarnings("unchecked")
List<Vertex> vertices = IteratorUtils.asList(iter);
Assert.assertEquals(size, vertices.size());
pageAll.addAll(vertices);
page = TraversalUtil.page(iter);
CloseableIterator.closeIterator(iter);
}
Assert.assertEquals(100, pageAll.size());
Assert.assertTrue(all.containsAll(pageAll));
if (page != null) {
iter = graph.traversal().V().has("~page", page);
long count = IteratorUtils.count(iter);
Assert.assertEquals(0L, count);
page = TraversalUtil.page(iter);
CloseableIterator.closeIterator(iter);
}
Assert.assertNull(page);
}
@Test
public void testQueryByPageWithInvalidPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
init100Books();
// Illegal base64 character
Assert.assertThrows(BackendException.class, () -> {
graph.traversal().V()
.has("~page", "!abc123#").limit(10)
.toList();
});
// Invalid page
Assert.assertThrows(BackendException.class, () -> {
graph.traversal().V()
.has("~page", "abc123").limit(10)
.toList();
});
}
@Test
public void testQueryByPageWithSpecialBase64Chars() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
final String pageWith3Base64Chars = "AAAAADsyABwAEAqI546LS6WW57unBgA" +
"EAAAAAPB////+8H////4alhxAZS8va6" +
"opcAKpklipAAQAAAAAAAAAAQ==";
final String pageWithSpace = "AAAAADsyABwAEAqI546LS6WW57unBgAEAAAAAP" +
"B//// 8H////4alhxAZS8va6opcAKpklipAAQA" +
"AAAAAAAAAQ==";
HugeGraph graph = graph();
init100Books();
// Contains valid character '+' and '/' and '='
GraphTraversal<Vertex, Vertex> traversal;
traversal = graph.traversal().V()
.has("~page", pageWith3Base64Chars).limit(10);
Assert.assertNotNull(traversal);
CloseableIterator.closeIterator(traversal);
// Contains invalid base64 character ' ', will be replaced to '+'
traversal = graph.traversal().V()
.has("~page", pageWithSpace).limit(10);
Assert.assertNotNull(traversal);
CloseableIterator.closeIterator(traversal);
}
@Test
public void testQueryByPageWithInvalidLimit() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
initPageTestData();
GraphTraversalSource g = graph.traversal();
long limit = Query.defaultCapacity() + 1;
Assert.assertThrows(IllegalStateException.class, () -> {
g.V().has("~page", "").limit(0).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().has("~page", "").limit(limit).toList();
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().has("name", "marko").has("~page", "").limit(limit).toList();
});
}
@Test
public void testQueryByPageWithCapacityAndNoLimit() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
initPageTestData();
GraphTraversalSource g = graph.traversal();
long capacity = 10;
long old = Query.defaultCapacity(capacity);
try {
GraphTraversal<Vertex, Vertex> iter;
iter = g.V().has("~page", "").limit(capacity);
Assert.assertEquals(10, IteratorUtils.count(iter));
CloseableIterator.closeIterator(iter);
Assert.assertThrows(IllegalArgumentException.class, () -> {
/*
* When query vertices/edge in page, the limit will be regard
* as page size, it shouldn't exceed capacity
*/
g.V().has("~page", "").limit(capacity + 1).toList();
});
Assert.assertThrows(LimitExceedException.class, () -> {
g.V().has("~page", "").limit(-1).toList();
});
} finally {
Query.defaultCapacity(old);
}
}
@Test
public void testQueryInPageWithoutCapacity() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
long old = Query.defaultCapacity(Query.NO_CAPACITY);
try {
GraphTraversal<Vertex, Vertex> iter;
iter = g.V().has("~page", "").limit(-1);
Assert.assertEquals(34, IteratorUtils.count(iter));
CloseableIterator.closeIterator(iter);
iter = g.V().has("~page", "").limit(20);
Assert.assertEquals(20, IteratorUtils.count(iter));
CloseableIterator.closeIterator(iter);
iter = g.V().has("age", 30).has("~page", "").limit(-1);
Assert.assertEquals(18, IteratorUtils.count(iter));
CloseableIterator.closeIterator(iter);
iter = g.V().has("age", 30).has("~page", "").limit(10);
Assert.assertEquals(10, IteratorUtils.count(iter));
CloseableIterator.closeIterator(iter);
} finally {
Query.defaultCapacity(old);
}
}
@Test
public void testQueryByPageWithOffset() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
init100Books();
Assert.assertThrows(IllegalStateException.class, () -> {
graph.traversal().V()
.has("~page", "").range(2, 10)
.toList();
});
}
@Test
public void testQueryByPageWithtUncommittedRecords() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "Canadian");
graph.addVertex(T.label, "author", "id", 2,
"name", "Guido van Rossum", "age", 61,
"lived", "California");
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.traversal().V()
.has("~page", "")
.toList();
});
}
@Test
public void testQueryByLabelInPageWithLimitLtePageSize() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("unknown").has("~page", "").limit(1).toList();
});
Assert.assertThrows(IllegalStateException.class, () -> {
g.V().hasLabel("programmer").has("~page", "").limit(0).toList();
});
List<Vertex> vertices = g.V().hasLabel("programmer")
.has("~page", "").limit(1)
.toList();
Assert.assertEquals(1, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("programmer", v.label());
});
vertices = g.V().hasLabel("software")
.has("~page", "").limit(5)
.toList();
Assert.assertEquals(5, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("software", v.label());
});
vertices = g.V().hasLabel("programmer")
.has("~page", "").limit(10)
.toList();
Assert.assertEquals(10, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("programmer", v.label());
});
}
@Test
public void testQueryByLabelInPageWithLimitGtPageSize() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
// Limit > page-size(10), test internal paging
List<Vertex> vertices = g.V().hasLabel("programmer")
.has("~page", "").limit(11)
.toList();
Assert.assertEquals(11, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("programmer", v.label());
});
vertices = g.V().hasLabel("software")
.has("~page", "").limit(15)
.toList();
Assert.assertEquals(15, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("software", v.label());
});
vertices = g.V().hasLabel("programmer")
.has("~page", "").limit(20)
.toList();
// Programmer only has 18
Assert.assertEquals(18, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("programmer", v.label());
});
}
@Test
public void testQueryBySingleLabelInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
GraphTraversal<Vertex, Vertex> iter = g.V().hasLabel("programmer")
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().hasLabel("programmer")
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().hasLabel("programmer")
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Vertex vertex2 = vertices.get(0);
Assert.assertEquals(vertex1.id(), vertex2.id());
Assert.assertEquals(vertex1.label(), vertex2.label());
Assert.assertEquals(IteratorUtils.asList(vertex1.properties()),
IteratorUtils.asList(vertex2.properties()));
vertices = g.V().hasLabel("programmer")
.has("~page", page).limit(17).toList();
Assert.assertEquals(17, vertices.size());
Vertex vertex3 = vertices.get(16);
vertices = g.V().hasLabel("programmer")
.has("~page", page).limit(18).toList();
Assert.assertEquals(17, vertices.size());
Vertex vertex4 = vertices.get(16);
Assert.assertEquals(vertex3.id(), vertex4.id());
Assert.assertEquals(vertex3.label(), vertex4.label());
Assert.assertEquals(IteratorUtils.asList(vertex3.properties()),
IteratorUtils.asList(vertex4.properties()));
}
@Test
public void testQueryByMultiLabelInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("unknown", "programmer")
.has("~page", "").limit(1)
.toList();
});
GraphTraversal<Vertex, Vertex> iter;
iter = g.V().hasLabel("programmer", "software").has("~page", "")
.limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().hasLabel("programmer", "software")
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().hasLabel("programmer", "software")
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Vertex vertex2 = vertices.get(0);
Assert.assertEquals(vertex1.id(), vertex2.id());
Assert.assertEquals(vertex1.label(), vertex2.label());
Assert.assertEquals(IteratorUtils.asList(vertex1.properties()),
IteratorUtils.asList(vertex2.properties()));
vertices = g.V().hasLabel("programmer", "software")
.has("~page", page).limit(18).toList();
Assert.assertEquals(18, vertices.size());
Vertex vertex3 = vertices.get(17);
vertices = g.V().hasLabel("programmer", "software")
.has("~page", page).limit(33).toList();
Assert.assertEquals(33, vertices.size());
Vertex vertex4 = vertices.get(17);
Assert.assertEquals(vertex3.id(), vertex4.id());
Assert.assertEquals(vertex3.label(), vertex4.label());
Assert.assertEquals(IteratorUtils.asList(vertex3.properties()),
IteratorUtils.asList(vertex4.properties()));
}
@Test
public void testQueryByPropertyInPageWithLimitLtePageSize() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
Assert.assertThrows(IllegalStateException.class, () -> {
g.V().has("name", "marko").has("~page", "").limit(0).toList();
});
// Secondary
List<Vertex> vertices = g.V().has("name", "marko")
.has("~page", "").limit(1)
.toList();
Assert.assertEquals(1, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("marko", v.value("name"));
});
// Range
vertices = g.V().has("price", P.between(200, 400))
.has("~page", "").limit(5)
.toList();
Assert.assertEquals(5, vertices.size());
vertices.forEach(v -> {
Assert.assertTrue((int) v.value("price") >= 200);
Assert.assertTrue((int) v.value("price") < 400);
});
// Search
vertices = g.V().has("city", Text.contains("Beijing"))
.has("~page", "").limit(10)
.toList();
Assert.assertEquals(10, vertices.size());
vertices.forEach(v -> {
Assert.assertTrue(((String) v.value("city")).contains("Beijing"));
});
}
@Test
public void testQueryByPropertyInPageWithLimitGtPageSize() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
// Limit > page-size(10), test internal paging
// Secondary
List<Vertex> vertices = g.V().has("name", "marko")
.has("~page", "").limit(11)
.toList();
Assert.assertEquals(11, vertices.size());
vertices.forEach(v -> {
Assert.assertEquals("marko", v.value("name"));
});
// Range
vertices = g.V().has("price", P.between(100, 400))
.has("~page", "").limit(15)
.toList();
Assert.assertEquals(12, vertices.size());
vertices.forEach(v -> {
Assert.assertTrue((int) v.value("price") >= 100);
Assert.assertTrue((int) v.value("price") < 400);
});
// Search
vertices = g.V().has("city", Text.contains("Beijing"))
.has("~page", "").limit(20)
.toList();
Assert.assertEquals(12, vertices.size());
vertices.forEach(v -> {
Assert.assertTrue(((String) v.value("city")).contains("Beijing"));
});
}
@Test
public void testQueryBySingleSecondaryPropertyInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
GraphTraversal<Vertex, Vertex> iter = g.V().has("name", "marko")
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().has("name", "marko")
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().has("name", "marko")
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
vertices = g.V().has("name", "marko")
.has("~page", page).limit(18).toList();
Assert.assertEquals(18, vertices.size());
Vertex vertex3 = vertices.get(17);
vertices = g.V().has("name", "marko")
.has("~page", page).limit(40).toList();
Assert.assertEquals(33, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
}
@Test
public void testQueryBySingleRangePropertyInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
GraphTraversal<Vertex, Vertex> iter = g.V().has("price", P.gte(100))
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().has("price", P.gte(100))
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().has("price", P.gte(100))
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
vertices = g.V().has("price", P.gte(100))
.has("~page", page).limit(11).toList();
Assert.assertEquals(11, vertices.size());
Vertex vertex3 = vertices.get(10);
vertices = g.V().has("price", P.gte(100))
.has("~page", page).limit(20).toList();
Assert.assertEquals(15, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
}
@Test
public void testQueryBySingleSearchPropertyInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
GraphTraversal<Vertex, Vertex> iter;
iter = g.V().has("city", Text.contains("Beijing Shanghai"))
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().has("city", Text.contains("Beijing Shanghai"))
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().has("city", Text.contains("Beijing Shanghai"))
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
vertices = g.V().has("city", Text.contains("Beijing Shanghai"))
.has("~page", page).limit(11).toList();
Assert.assertEquals(11, vertices.size());
Vertex vertex3 = vertices.get(10);
vertices = g.V().has("city", Text.contains("Beijing Shanghai"))
.has("~page", page).limit(20).toList();
Assert.assertEquals(17, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
}
@Test
public void testQueryByCompositePropertyInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
GraphTraversal<Vertex, Vertex> iter;
iter = g.V().has("name", "marko").has("age", 30)
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().has("name", "marko").has("age", 30)
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().has("name", "marko").has("age", 30)
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
vertices = g.V().has("name", "marko").has("age", 30)
.has("~page", page).limit(11).toList();
Assert.assertEquals(11, vertices.size());
Vertex vertex3 = vertices.get(10);
vertices = g.V().has("name", "marko").has("age", 30)
.has("~page", page).limit(40).toList();
Assert.assertEquals(17, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
}
@Test
public void testQueryByJointPropertyInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
Assert.assertThrows(HugeException.class, () -> {
g.V().has("name", "marko").has("city", Text.contains("Beijing"))
.has("~page", "").limit(10).toList();
});
Assert.assertThrows(HugeException.class, () -> {
g.V().has("age", 30).has("city", Text.contains("Beijing"))
.has("~page", "").limit(10).toList();
});
Assert.assertThrows(HugeException.class, () -> {
g.V().has("name", "marko").has("lang", "java")
.has("~page", "").limit(10).toList();
});
Assert.assertThrows(HugeException.class, () -> {
g.V().has("lang", "java").has("price", 200)
.has("~page", "").limit(10).toList();
});
}
@Test
public void testQueryByRangeIndexInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
initPageTestData();
// There are 4 vertices matched
GraphTraversal<Vertex, Vertex> iter = g.V().hasLabel("software")
.has("price", P.eq(100))
.has("~page", "")
.limit(3);
List<Vertex> vertices1 = IteratorUtils.list(iter);
String page = TraversalUtil.page(iter);
Assert.assertEquals(3, vertices1.size());
List<Vertex> vertices2 = g.V().hasLabel("software")
.has("price", P.eq(100))
.has("~page", page).limit(3)
.toList();
Assert.assertEquals(1, vertices2.size());
Assert.assertTrue(CollectionUtil.intersect(vertices1, vertices2)
.isEmpty());
// There are 8 vertices matched
iter = g.V().hasLabel("software")
.has("price", P.gt(200))
.has("~page", "")
.limit(5);
vertices1 = IteratorUtils.list(iter);
Assert.assertEquals(5, vertices1.size());
page = TraversalUtil.page(iter);
vertices2 = g.V().hasLabel("software").has("price", P.gt(200))
.has("~page", page).limit(5).toList();
Assert.assertEquals(3, vertices2.size());
Assert.assertTrue(CollectionUtil.intersect(vertices1, vertices2)
.isEmpty());
// There are 8 vertices matched
iter = g.V().hasLabel("software")
.has("price", P.lt(300))
.has("~page", "")
.limit(5);
vertices1 = IteratorUtils.list(iter);
Assert.assertEquals(5, vertices1.size());
page = TraversalUtil.page(iter);
vertices2 = g.V().hasLabel("software").has("price", P.lt(300))
.has("~page", page).limit(5).toList();
Assert.assertEquals(3, vertices2.size());
Assert.assertTrue(CollectionUtil.intersect(vertices1, vertices2)
.isEmpty());
}
@Test
public void testQueryByUnionIndexInPageWithSomeIndexNoData() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
GraphTraversalSource g = graph.traversal();
initPageTestData();
// Author has index by name but no data
schema.indexLabel("authorByName")
.onV("author")
.by("name")
.secondary()
.ifNotExist()
.create();
GraphTraversal<Vertex, Vertex> iter = g.V().has("name", "marko")
.has("~page", "").limit(1);
Assert.assertEquals(1, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
List<Vertex> vertices;
vertices = g.V().has("name", "marko")
.has("~page", page).limit(1).toList();
Assert.assertEquals(1, vertices.size());
Vertex vertex1 = vertices.get(0);
vertices = g.V().has("name", "marko")
.has("~page", page).limit(9).toList();
Assert.assertEquals(9, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
vertices = g.V().has("name", "marko")
.has("~page", page).limit(18).toList();
Assert.assertEquals(18, vertices.size());
Vertex vertex3 = vertices.get(17);
vertices = g.V().has("name", "marko")
.has("~page", page).limit(40).toList();
Assert.assertEquals(33, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
}
@Test
public void testQueryBySecondaryIndexWithLimitAndOffset() {
initPersonIndex(true);
init5Persons();
List<Vertex> vertices = graph().traversal().V()
.has("city", "Beijing").toList();
Assert.assertEquals(3, vertices.size());
List<Vertex> verticesSkip = graph().traversal().V()
.has("city", "Beijing")
.skip(1).toList();
Assert.assertEquals(2, verticesSkip.size());
Set<Vertex> vertices1 = graph().traversal().V()
.has("city", "Beijing")
.range(0, 2).toSet();
Assert.assertEquals(2, vertices1.size());
Set<Vertex> vertices2 = graph().traversal().V()
.has("city", "Beijing")
.range(2, 3).toSet();
Assert.assertEquals(1, vertices2.size());
vertices1.addAll(vertices2);
Assert.assertEquals(vertices.size(), vertices1.size());
Assert.assertTrue(vertices.containsAll(vertices1));
}
@Test
public void testQueryByRangeIndexWithLimitAndOffset() {
initPersonIndex(false);
init5Persons();
List<Vertex> vertices = graph().traversal().V()
.has("age", P.between(5, 22)).toList();
Assert.assertEquals(4, vertices.size());
List<Vertex> verticesSkip = graph().traversal().V()
.has("age", P.between(5, 22))
.skip(1).toList();
Assert.assertEquals(3, verticesSkip.size());
Set<Vertex> vertices1 = graph().traversal().V()
.has("age", P.between(5, 22))
.range(0, 3).toSet();
Assert.assertEquals(3, vertices1.size());
Set<Vertex> vertices2 = graph().traversal().V()
.has("age", P.between(5, 22))
.range(3, 4).toSet();
Assert.assertEquals(1, vertices2.size());
vertices1.addAll(vertices2);
Assert.assertEquals(vertices.size(), vertices1.size());
Assert.assertTrue(vertices.containsAll(vertices1));
}
@Test
public void testQueryByLabelIndexWithLimitAndOffset() {
init5Persons();
List<Vertex> vertices = graph().traversal().V().hasLabel("person")
.toList();
Assert.assertEquals(5, vertices.size());
List<Vertex> verticesSkip = graph().traversal().V().hasLabel("person")
.skip(1).toList();
Assert.assertEquals(4, verticesSkip.size());
Set<Vertex> vertices1 = graph().traversal().V()
.hasLabel("person")
.range(0, 3).toSet();
Assert.assertEquals(3, vertices1.size());
Set<Vertex> vertices2 = graph().traversal().V()
.hasLabel("person")
.range(3, 5).toSet();
Assert.assertEquals(2, vertices2.size());
Set<Vertex> vertices3 = graph().traversal().V()
.hasLabel("person")
.limit(4).toSet();
Assert.assertEquals(4, vertices3.size());
vertices1.addAll(vertices2);
Assert.assertEquals(vertices.size(), vertices1.size());
Assert.assertTrue(vertices.containsAll(vertices1));
}
@Test
public void testAddCustomizedIdVerticesContainsExisted() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("programmer")
.useCustomizeStringId()
.properties("name", "age", "city")
.create();
schema.vertexLabel("designer")
.useCustomizeStringId()
.properties("name", "age", "city")
.create();
graph.addVertex(T.label, "programmer", T.id, "123456", "name", "marko",
"age", 18, "city", "Beijing");
this.commitTx();
graph.addVertex(T.label, "programmer", T.id, "123456", "name", "marko",
"age", 19, "city", "Beijing");
this.commitTx();
graph.addVertex(T.label, "designer", T.id, "123456", "name", "marko",
"age", 18, "city", "Beijing");
Assert.assertThrows(HugeException.class, () -> {
this.commitTx();
});
}
@Test
public void testQueryVerticesByIdsWithHasIdFilterAndNumberId() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("user").useCustomizeNumberId().create();
graph.addVertex(T.label, "user", T.id, 123);
graph.addVertex(T.label, "user", T.id, 456);
graph.addVertex(T.label, "user", T.id, 789);
this.mayCommitTx();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices;
vertices = g.V().hasId(P.within(123)).toList();
Assert.assertEquals(1, vertices.size());
vertices = g.V(123, 456).hasId(P.within(123)).toList();
Assert.assertEquals(1, vertices.size());
vertices = g.V(123, 456).hasId(123).toList();
Assert.assertEquals(1, vertices.size());
vertices = g.V(123, 456, 789).hasId(P.within(123, 456)).toList();
Assert.assertEquals(2, vertices.size());
vertices = g.V(123, 456, 789).hasId(456, 789).toList();
Assert.assertEquals(2, vertices.size());
vertices = g.V(123, 456, 789).hasId(P.within(123, 456, 789)).toList();
Assert.assertEquals(3, vertices.size());
}
@Test
public void testQueryVerticesByLabelsWithOneLabelNotExist() {
HugeGraph graph = graph();
SchemaManager schema = graph.schema();
schema.vertexLabel("user1").useCustomizeNumberId().create();
schema.vertexLabel("user2").useCustomizeNumberId().create();
graph.addVertex(T.label, "user1", T.id, 123);
graph.addVertex(T.label, "user2", T.id, 456);
graph.addVertex(T.label, "user2", T.id, 789);
this.mayCommitTx();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices;
vertices = g.V().hasLabel("user1").toList();
Assert.assertEquals(1, vertices.size());
vertices = g.V().hasLabel("user2").toList();
Assert.assertEquals(2, vertices.size());
vertices = g.V().hasLabel("user1", "user2").toList();
Assert.assertEquals(3, vertices.size());
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("user3").toList();
}, e -> {
Assert.assertEquals("Undefined vertex label: 'user3'",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("user1", "user3").toList();
}, e -> {
Assert.assertEquals("Undefined vertex label: 'user3'",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("user3", "user1").toList();
}, e -> {
Assert.assertEquals("Undefined vertex label: 'user3'",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("user3", "user4").toList();
}, e -> {
Assert.assertEquals("Undefined vertex label: 'user3'",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
g.V().hasLabel("user4", "user3").toList();
}, e -> {
Assert.assertEquals("Undefined vertex label: 'user4'",
e.getMessage());
});
}
@Test
public void testQueryByJointLabels() {
HugeGraph graph = graph();
init5Persons();
init5Computers();
init10Vertices();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices = g.V().hasLabel("person").hasLabel("computer")
.toList();
Assert.assertEquals(0, vertices.size());
vertices = g.V().hasLabel("person").hasLabel("person").toList();
Assert.assertEquals(5, vertices.size());
vertices = g.V().hasLabel("person", "computer").hasLabel("person")
.toList();
Assert.assertEquals(5, vertices.size());
for (Vertex vertex : vertices) {
Assert.assertEquals("person", vertex.label());
}
vertices = g.V().hasLabel("person", "computer").hasLabel("computer")
.toList();
Assert.assertEquals(5, vertices.size());
for (Vertex vertex : vertices) {
Assert.assertEquals("computer", vertex.label());
}
vertices = g.V().hasLabel("person").hasLabel("person", "computer")
.toList();
Assert.assertEquals(5, vertices.size());
for (Vertex vertex : vertices) {
Assert.assertEquals("person", vertex.label());
}
vertices = g.V().hasLabel("person", "computer")
.hasLabel("person", "author").toList();
Assert.assertEquals(5, vertices.size());
for (Vertex vertex : vertices) {
Assert.assertEquals("person", vertex.label());
}
vertices = g.V().hasLabel("person", "computer")
.hasLabel("book", "language").toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByHasIdEmptyList() {
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices = g.V().hasId(Collections.EMPTY_LIST).toList();
Assert.assertEquals(0, vertices.size());
}
@Test
public void testQueryByHasIdEmptyListInPage() {
Assume.assumeTrue("Not support paging",
storeFeatures().supportsQueryByPage());
HugeGraph graph = graph();
GraphTraversalSource g = graph.traversal();
GraphTraversal<Vertex, Vertex> iter = g.V()
.hasId(Collections.EMPTY_LIST)
.has("~page", "").limit(1);
Assert.assertEquals(0, IteratorUtils.count(iter));
String page = TraversalUtil.page(iter);
Assert.assertNull(page);
}
@Test
public void testAddVertexWithSpecialSymbolInPrimaryValues() {
HugeGraph graph = graph();
Vertex vertex1 = graph.addVertex(T.label, "person", "name",
"xyz\u0001abc", "city", "Hongkong",
"age", 11);
Vertex vertex2 = graph.addVertex(T.label, "person", "name",
"xyz\u0002abc", "city", "Hongkong",
"age", 12);
Vertex vertex3 = graph.addVertex(T.label, "person", "name",
"xyz\u0003abc", "city", "Hongkong",
"age", 13);
this.mayCommitTx();
GraphTraversalSource g = graph.traversal();
Assert.assertEquals(vertex1, g.V().hasLabel("person")
.has("name", "xyz\u0001abc").next());
Assert.assertEquals(vertex2, g.V().hasLabel("person")
.has("name", "xyz\u0002abc").next());
Assert.assertEquals(vertex3, g.V().hasLabel("person")
.has("name", "xyz\u0003abc").next());
if (!graph.backend().equals("postgresql")) {
Vertex vertex0 = graph.addVertex(T.label, "person", "name",
"xyz\u0000abc", "city", "Hongkong",
"age", 10);
Assert.assertEquals(vertex0, g.V().hasLabel("person")
.has("name", "xyz\u0000abc").next());
}
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name",
"\u0000", "city", "Hongkong",
"age", 15);
}, e -> {
graph.tx().rollback();
Assert.assertContains("Illegal leading char '\\u0' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name",
"\u0001", "city", "Hongkong",
"age", 15);
}, e -> {
graph.tx().rollback();
Assert.assertContains("Illegal leading char '\\u1' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name",
"\u0002", "city", "Hongkong",
"age", 15);
}, e -> {
graph.tx().rollback();
Assert.assertContains("Illegal leading char '\\u2' in index",
e.getMessage());
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
graph.addVertex(T.label, "person", "name",
"\u0003", "city", "Hongkong",
"age", 15);
}, e -> {
graph.tx().rollback();
Assert.assertContains("Illegal leading char '\\u3' in index",
e.getMessage());
});
}
@Test
public void testQueryBySearchIndexWithSpecialSymbol() {
HugeGraph graph = graph();
graph.schema().indexLabel("personByCity")
.onV("person")
.by("city")
.search()
.ifNotExist().create();
Vertex vertex1 = graph.addVertex(T.label, "person", "name", "1",
"city", "xyz\u0002abc",
"age", 15);
Vertex vertex2 = graph.addVertex(T.label, "person", "name", "2",
"city", "\u0002",
"age", 15);
Vertex vertex3 = graph.addVertex(T.label, "person", "name", "3",
"city", "xyz\u0003abc",
"age", 15);
Vertex vertex4 = graph.addVertex(T.label, "person", "name", "4",
"city", "\u0003",
"age", 15);
Vertex vertex5 = graph.addVertex(T.label, "person", "name", "5",
"city", "xyz\u0001abc",
"age", 15);
Vertex vertex6 = graph.addVertex(T.label, "person", "name", "6",
"city", "\u0001",
"age", 15);
this.commitTx();
GraphTraversalSource g = graph.traversal();
String city;
city = g.V().hasLabel("person").has("name", "1")
.next().value("city");
Assert.assertEquals(vertex1.value("city"), city);
city = g.V().hasLabel("person").has("name", "2")
.next().value("city");
Assert.assertEquals(vertex2.value("city"), city);
city = g.V().hasLabel("person").has("name", "3")
.next().value("city");
Assert.assertEquals(vertex3.value("city"), city);
city = g.V().hasLabel("person").has("name", "4")
.next().value("city");
Assert.assertEquals(vertex4.value("city"), city);
city = g.V().hasLabel("person").has("name", "5")
.next().value("city");
Assert.assertEquals(vertex5.value("city"), city);
city = g.V().hasLabel("person").has("name", "6")
.next().value("city");
Assert.assertEquals(vertex6.value("city"), city);
List<Vertex> vertices;
vertices = g.V().has("city", Text.contains("abc")).toList();
Assert.assertEquals(3, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
Assert.assertTrue(vertices.contains(vertex3));
Assert.assertTrue(vertices.contains(vertex5));
vertices = g.V().has("city", Text.contains("\u0002")).toList();
Assert.assertEquals(0, vertices.size());
vertices = g.V().has("city", Text.contains("\u0003")).toList();
Assert.assertEquals(0, vertices.size());
vertices = g.V().has("city", Text.contains("\u0001")).toList();
Assert.assertEquals(0, vertices.size());
String backend = graph.backend();
if (ImmutableSet.of("rocksdb", "hbase").contains(backend)) {
Assert.assertThrows(Exception.class, () -> {
graph.addVertex(T.label, "person", "name", "0",
"city", "xyz\u0000efg", "age", 0);
graph.tx().commit();
}, e -> {
Assert.assertContains("can't contains byte '0x00'",
e.getMessage());
});
} else if (backend.equals("postgresql")) {
Assert.assertThrows(BackendException.class, () -> {
graph.addVertex(T.label, "person", "name", "7",
"city", "xyz\u0000efg",
"age", 15);
graph.tx().commit();
}, e -> {
graph.tx().rollback();
Assert.assertContains("invalid byte sequence for encoding " +
"\"UTF8\": 0x00",
e.getCause().getMessage());
});
} else {
graph.addVertex(T.label, "person", "name", "8",
"city", "xyz\u0000efg",
"age", 15);
graph.addVertex(T.label, "person", "name", "9",
"city", "\u0000",
"age", 15);
graph.tx().commit();
Assert.assertTrue(g.V().hasLabel("person")
.has("city", Text.contains("efg"))
.hasNext());
Assert.assertFalse(g.V().hasLabel("person")
.has("city", Text.contains("u0000"))
.hasNext());
}
}
@Test
public void testEnhanceTextMatch() {
HugeGraph graph = graph();
graph.schema().indexLabel("personByName").onV("person")
.by("name").search().ifNotExist().create();
Vertex vertex1 = graph.addVertex(T.label, "person", "name", "秦始皇",
"city", "Hongkong", "age", 15);
Vertex vertex2 = graph.addVertex(T.label, "person", "name", "始皇",
"city", "Hongkong", "age", 18);
Vertex vertex3 = graph.addVertex(T.label, "person", "name", "秦始皇2",
"city", "Beijing", "age", 21);
Vertex vertex4 = graph.addVertex(T.label, "person", "name", "秦始皇3",
"city", "Beijing", "age", 23);
Vertex vertex5 = graph.addVertex(T.label, "person", "name", "秦始皇帝",
"city", "Beijing", "age", 29);
this.commitTx();
GraphTraversalSource g = graph.traversal();
List<Vertex> vertices;
vertices = g.V().has("name", Text.contains("秦始皇")).toList();
Assert.assertEquals(5, vertices.size());
Assert.assertTrue(vertices.contains(vertex2));
vertices = g.V().has("name", Text.contains("(秦始皇)")).toList();
Assert.assertEquals(4, vertices.size());
Assert.assertTrue(vertices.contains(vertex1));
Assert.assertTrue(vertices.contains(vertex3));
Assert.assertTrue(vertices.contains(vertex4));
Assert.assertTrue(vertices.contains(vertex5));
vertices = g.V().has("name", Text.contains("(秦始皇帝)")).toList();
Assert.assertEquals(1, vertices.size());
Assert.assertTrue(vertices.contains(vertex5));
vertices = g.V().has("name", Text.contains("(秦始皇2|秦始皇3)")).toList();
Assert.assertEquals(2, vertices.size());
Assert.assertTrue(vertices.contains(vertex3));
Assert.assertTrue(vertices.contains(vertex4));
}
private void init10VerticesAndCommit() {
this.init10Vertices();
this.commitTx();
}
private void init10Vertices() {
HugeGraph graph = graph();
graph.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "Canadian");
graph.addVertex(T.label, "author", "id", 2,
"name", "Guido van Rossum", "age", 61,
"lived", "California");
graph.addVertex(T.label, "language", "name", "java");
graph.addVertex(T.label, "language", "name", "c++");
graph.addVertex(T.label, "language", "name", "python",
"dynamic", true);
graph.addVertex(T.label, "book", "name", "java-1");
graph.addVertex(T.label, "book", "name", "java-2");
graph.addVertex(T.label, "book", "name", "java-3");
graph.addVertex(T.label, "book", "name", "java-4");
graph.addVertex(T.label, "book", "name", "java-5");
this.mayCommitTx();
}
private void init100Books() {
HugeGraph graph = graph();
for (int i = 0; i < 100; i++) {
graph.addVertex(T.label, "book", "name", "java-" + i, "price", i);
}
this.commitTx();
}
private void init5Persons() {
HugeGraph graph = graph();
graph.addVertex(T.label, "person", "name", "Baby",
"city", "Hongkong", "age", 3,
"birth", Utils.date("2012-01-01"));
graph.addVertex(T.label, "person", "name", "James",
"city", "Beijing", "age", 19,
"birth", Utils.date("2013-01-01 00:00:00.000"));
graph.addVertex(T.label, "person", "name", "Tom Cat",
"city", "Beijing", "age", 20,
"birth", Utils.date("2014-01-01 00:00:00"));
graph.addVertex(T.label, "person", "name", "Lisa",
"city", "Beijing", "age", 20,
"birth", Utils.date("2015-01-01 00:00:00.000"));
graph.addVertex(T.label, "person", "name", "Hebe",
"city", "Taipei", "age", 21,
"birth", Utils.date("2016-01-01 00:00:00.000"));
this.commitTx();
}
private void init100Persons() {
HugeGraph graph = graph();
for (int i = 0; i < 100; i++) {
graph.addVertex(T.label, "person", "name", "person-" + i,
"city", i % 2 == 0 ? "Beijing" : "Hongkong",
"birth", i % 10 == 3 ? Utils.date("2012-01-01") :
Utils.date("2018-01-01"),
"age", i % 11);
}
this.commitTx();
}
private void init5Computers() {
this.initComputerIndex();
HugeGraph graph = graph();
graph.addVertex(T.label, "computer", "name", "YangTian T6900C",
"band", "lenovo", "cpu", "3.2GHz", "ram", "8GB",
"price", 4599);
graph.addVertex(T.label, "computer", "name", "Fengxing K450e",
"band", "lenovo", "cpu", "3.2GHz", "ram", "16GB",
"price", 6099);
graph.addVertex(T.label, "computer", "name", "iMac MK482CH/A",
"band", "apple", "cpu", "3.3GHz", "ram", "32GB",
"price", 15990);
graph.addVertex(T.label, "computer", "name", "Surface Studio",
"band", "microsoft", "cpu", "4.6GHz", "ram", "32GB",
"price", 35990);
graph.addVertex(T.label, "computer", "name", "Zen AIO Pro",
"band", "asus", "cpu", "3.2GHz", "ram", "16GB",
"price", 6999);
this.commitTx();
}
private void initPageTestData() {
SchemaManager schema = graph().schema();
schema.propertyKey("lang").asText().ifNotExist().create();
schema.vertexLabel("programmer")
.properties("name", "age", "city")
.useCustomizeStringId()
.nullableKeys("age")
.ifNotExist()
.create();
schema.vertexLabel("software")
.properties("name", "lang", "price")
.useCustomizeStringId()
.nullableKeys("price")
.ifNotExist()
.create();
schema.indexLabel("programmerByNameAndAge")
.onV("programmer")
.by("name", "age")
.secondary()
.ifNotExist()
.create();
schema.indexLabel("programmerByAge")
.onV("programmer")
.range()
.by("age")
.ifNotExist()
.create();
schema.indexLabel("programmerByCity")
.onV("programmer")
.search()
.by("city")
.ifNotExist()
.create();
schema.indexLabel("softwareByName")
.onV("software")
.secondary()
.by("name")
.ifNotExist()
.create();
schema.indexLabel("softwareByLang")
.onV("software")
.secondary()
.by("lang")
.ifNotExist()
.create();
schema.indexLabel("softwareByPrice")
.onV("software")
.by("price")
.range()
.ifNotExist()
.create();
String[] cities = {"Beijing Haidian", "Beijing Chaoyang", "Shanghai"};
for (int i = 1; i <= 18; i++) {
String id = "p_marko" + i;
/*
* The city of each programmer is:
* [1, 6]: Beijing Haidian, [7, 12]: Beijing Chaoyang,
* [13, 18]: Shanghai
*/
String city = cities[(i - 1) / 6];
graph().addVertex(T.label, "programmer", T.id, id, "name", "marko",
"age", 30, "city", city);
}
for (int i = 1; i <= 16; i++) {
String id = "s_marko" + i;
/*
* The price of each software is:
* [1, 4]: 100, [5, 8]: 200, [9, 12]: 300, [13, 16]: 400
*/
int price = ((i - 1) / 4 + 1) * 100;
graph().addVertex(T.label, "software", T.id, id, "name", "marko",
"lang", "java", "price", price);
}
this.commitTx();
}
private Vertex vertex(String label, String pkName, Object pkValue) {
List<Vertex> vertices = graph().traversal().V()
.hasLabel(label).has(pkName, pkValue)
.toList();
Assert.assertTrue(vertices.size() <= 1);
return vertices.size() == 1 ? vertices.get(0) : null;
}
private static void assertContains(List<Vertex> vertices,
Object... keyValues) {
Assert.assertTrue(Utils.contains(vertices, new FakeObjects.FakeVertex(keyValues)));
}
private static void assertNotContains(List<Vertex> vertices,
Object... keyValues) {
Assert.assertFalse(Utils.contains(vertices, new FakeObjects.FakeVertex(keyValues)));
}
}