blob: 3eac6d043fa00c64ac3cb0b2777cd56a7305c072 [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.example;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import org.apache.hugegraph.HugeFactory;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.BackendException;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.backend.query.ConditionQuery;
import org.apache.hugegraph.backend.tx.GraphTransaction;
import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.testutil.Whitebox;
import org.apache.hugegraph.traversal.optimize.Text;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.Directions;
import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.util.Log;
public class Example1 {
private static final Logger LOG = Log.logger(Example1.class);
public static void main(String[] args) throws Exception {
LOG.info("Example1 start!");
HugeGraph graph = ExampleUtil.loadGraph();
Example1.showFeatures(graph);
Example1.loadSchema(graph);
Example1.loadData(graph);
Example1.testQuery(graph);
Example1.testRemove(graph);
Example1.testVariables(graph);
Example1.testLeftIndexProcess(graph);
Example1.thread(graph);
graph.close();
HugeFactory.shutdown(30L);
}
private static void thread(HugeGraph graph) throws InterruptedException {
Thread t = new Thread(() -> {
// Default tx
graph.addVertex(T.label, "book", "name", "java-11");
graph.addVertex(T.label, "book", "name", "java-12");
graph.tx().commit();
// New tx
GraphTransaction tx = Whitebox.invoke(graph.getClass(),
"openGraphTransaction",
graph);
tx.addVertex(T.label, "book", "name", "java-21");
tx.addVertex(T.label, "book", "name", "java-22");
tx.commit();
tx.close();
// This will close the schema tx
Whitebox.invoke(graph.getClass(), "closeTx", graph);
});
t.start();
t.join();
}
public static void showFeatures(final HugeGraph graph) {
LOG.info("SupportsPersistence: {}",
graph.features().graph().supportsPersistence());
}
public static void loadSchema(final HugeGraph graph) {
SchemaManager schema = graph.schema();
// Schema changes will be commit directly into the back-end
LOG.info("=============== propertyKey ================");
schema.propertyKey("id").asInt().create();
schema.propertyKey("name").asText().create();
schema.propertyKey("gender").asText().create();
schema.propertyKey("instructions").asText().create();
schema.propertyKey("category").asText().create();
schema.propertyKey("year").asInt().create();
schema.propertyKey("time").asText().create();
schema.propertyKey("timestamp").asDate().create();
schema.propertyKey("ISBN").asText().create();
schema.propertyKey("calories").asInt().create();
schema.propertyKey("amount").asText().create();
schema.propertyKey("stars").asInt().create();
schema.propertyKey("age").asInt().valueSingle().create();
schema.propertyKey("comment").asText().valueSet().create();
schema.propertyKey("contribution").asText().valueSet().create();
schema.propertyKey("nickname").asText().valueList().create();
schema.propertyKey("lived").asText().create();
schema.propertyKey("country").asText().valueSet().create();
schema.propertyKey("city").asText().create();
schema.propertyKey("sensor_id").asUUID().create();
schema.propertyKey("versions").asInt().valueList().create();
LOG.info("=============== vertexLabel ================");
schema.vertexLabel("person")
.properties("name", "age", "city")
.primaryKeys("name")
.create();
schema.vertexLabel("author")
.properties("id", "name", "age", "lived")
.primaryKeys("id").create();
schema.vertexLabel("language").properties("name", "versions")
.primaryKeys("name").create();
schema.vertexLabel("recipe").properties("name", "instructions")
.primaryKeys("name").create();
schema.vertexLabel("book").properties("name")
.primaryKeys("name").create();
schema.vertexLabel("reviewer").properties("name", "timestamp")
.primaryKeys("name").create();
// vertex label must have the properties that specified in primary key
schema.vertexLabel("FridgeSensor").properties("city")
.primaryKeys("city").create();
LOG.info("=============== vertexLabel & index ================");
schema.indexLabel("personByCity")
.onV("person").secondary().by("city").create();
schema.indexLabel("personByAge")
.onV("person").range().by("age").create();
schema.indexLabel("authorByLived")
.onV("author").search().by("lived").create();
// schemaManager.getVertexLabel("author").index("byName").secondary().by("name").add();
// schemaManager.getVertexLabel("recipe").index("byRecipe").materialized().by("name").add();
// schemaManager.getVertexLabel("meal").index("byMeal").materialized().by("name").add();
// schemaManager.getVertexLabel("ingredient").index("byIngredient").materialized()
// .by("name").add();
// schemaManager.getVertexLabel("reviewer").index("byReviewer").materialized()
// .by("name").add();
LOG.info("=============== edgeLabel ================");
schema.edgeLabel("authored").singleTime()
.sourceLabel("author").targetLabel("book")
.properties("contribution", "comment")
.nullableKeys("comment")
.create();
schema.edgeLabel("write").multiTimes().properties("time")
.sourceLabel("author").targetLabel("book")
.sortKeys("time")
.create();
schema.edgeLabel("look").multiTimes().properties("timestamp")
.sourceLabel("person").targetLabel("book")
.sortKeys("timestamp")
.create();
schema.edgeLabel("created").singleTime()
.sourceLabel("author").targetLabel("language")
.create();
schema.edgeLabel("rated")
.sourceLabel("reviewer").targetLabel("recipe")
.create();
}
public static void loadData(final HugeGraph graph) {
// will auto open tx (would not auto commit)
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);
graph.tx().commit();
// must commit manually with new backend tx (independent of tinkerpop)
GraphTransaction tx = Whitebox.invoke(graph.getClass(),
"openGraphTransaction",
graph);
LOG.info("=============== addVertex ================");
Vertex james = tx.addVertex(T.label, "author", "id", 1,
"name", "James Gosling", "age", 62,
"lived", "San Francisco Bay Area");
Vertex java = tx.addVertex(T.label, "language", "name", "java",
"versions", Arrays.asList(6, 7, 8));
Vertex book1 = tx.addVertex(T.label, "book", "name", "java-1");
Vertex book2 = tx.addVertex(T.label, "book", "name", "java-2");
Vertex book3 = tx.addVertex(T.label, "book", "name", "java-3");
james.addEdge("created", java);
james.addEdge("authored", book1,
"contribution", "1990-1-1",
"comment", "it's a good book",
"comment", "it's a good book",
"comment", "it's a good book too");
james.addEdge("authored", book2, "contribution", "2017-4-28");
james.addEdge("write", book2, "time", "2017-4-28");
james.addEdge("write", book3, "time", "2016-1-1");
james.addEdge("write", book3, "time", "2017-4-28");
// commit data changes
try {
tx.commit();
} catch (BackendException e) {
e.printStackTrace();
try {
tx.rollback();
} catch (BackendException e2) {
e2.printStackTrace();
}
} finally {
tx.close();
}
// use the manually open transaction (tinkerpop tx)
graph.tx().open();
graph.addVertex(T.label, "book", "name", "java-3");
graph.addVertex(T.label, "book", "name", "java-4");
graph.addVertex(T.label, "book", "name", "java-5");
graph.tx().commit();
}
public static void testQuery(final HugeGraph graph) {
// query all
GraphTraversal<Vertex, Vertex> vertices = graph.traversal().V();
int size = vertices.toList().size();
assert size == 12;
LOG.info(">>>> query all vertices: size {}", size);
// query by label
vertices = graph.traversal().V().hasLabel("person");
size = vertices.toList().size();
assert size == 5;
LOG.info(">>>> query all persons: size {}", size);
// query vertex by primary-values
vertices = graph.traversal().V().hasLabel("author").has("id", 1);
List<Vertex> vertexList = vertices.toList();
assert vertexList.size() == 1;
LOG.info(">>>> query vertices by primary-values: {}", vertexList);
VertexLabel author = graph.schema().getVertexLabel("author");
String authorId = String.format("%s:%s", author.id().asString(), "11");
// query vertex by id and query out edges
vertices = graph.traversal().V(authorId);
GraphTraversal<Vertex, Edge> edgesOfVertex = vertices.outE("created");
List<Edge> edgeList = edgesOfVertex.toList();
assert edgeList.size() == 1;
LOG.info(">>>> query edges of vertex: {}", edgeList);
vertices = graph.traversal().V(authorId);
vertexList = vertices.out("created").toList();
assert vertexList.size() == 1;
LOG.info(">>>> query vertices of vertex: {}", vertexList);
// query edge by sort-values
vertices = graph.traversal().V(authorId);
edgesOfVertex = vertices.outE("write").has("time", "2017-4-28");
edgeList = edgesOfVertex.toList();
assert edgeList.size() == 2;
LOG.info(">>>> query edges of vertex by sort-values: {}", edgeList);
// query vertex by condition (filter by property name)
ConditionQuery q = new ConditionQuery(HugeType.VERTEX);
PropertyKey age = graph.propertyKey("age");
q.key(HugeKeys.PROPERTIES, age.id());
if (graph.backendStoreFeatures()
.supportsQueryWithContainsKey()) {
Iterator<Vertex> iter = graph.vertices(q);
assert iter.hasNext();
LOG.info(">>>> queryVertices(age): {}", iter.hasNext());
while (iter.hasNext()) {
LOG.info(">>>> queryVertices(age): {}", iter.next());
}
}
// query all edges
GraphTraversal<Edge, Edge> edges = graph.traversal().E().limit(2);
size = edges.toList().size();
assert size == 2;
LOG.info(">>>> query all edges with limit 2: size {}", size);
// query edge by id
EdgeLabel authored = graph.edgeLabel("authored");
VertexLabel book = graph.schema().getVertexLabel("book");
String book1Id = String.format("%s:%s", book.id().asString(), "java-1");
String book2Id = String.format("%s:%s", book.id().asString(), "java-2");
String edgeId = String.format("S%s>%s>%s>S%s",
authorId, authored.id(), "", book2Id);
edges = graph.traversal().E(edgeId);
edgeList = edges.toList();
assert edgeList.size() == 1;
LOG.info(">>>> query edge by id: {}", edgeList);
Edge edge = edgeList.get(0);
edges = graph.traversal().E(edge.id());
edgeList = edges.toList();
assert edgeList.size() == 1;
LOG.info(">>>> query edge by id: {}", edgeList);
// query edge by condition
q = new ConditionQuery(HugeType.EDGE);
q.eq(HugeKeys.OWNER_VERTEX, IdGenerator.of(authorId));
q.eq(HugeKeys.DIRECTION, Directions.OUT);
q.eq(HugeKeys.LABEL, authored.id());
q.eq(HugeKeys.SORT_VALUES, "");
q.eq(HugeKeys.OTHER_VERTEX, IdGenerator.of(book1Id));
Iterator<Edge> edges2 = graph.edges(q);
assert edges2.hasNext();
LOG.info(">>>> queryEdges(id-condition): {}", edges2.hasNext());
while (edges2.hasNext()) {
LOG.info(">>>> queryEdges(id-condition): {}", edges2.next());
}
// NOTE: query edge by has-key just supported by Cassandra
if (graph.backendStoreFeatures().supportsQueryWithContainsKey()) {
PropertyKey contribution = graph.propertyKey("contribution");
q.key(HugeKeys.PROPERTIES, contribution.id());
Iterator<Edge> edges3 = graph.edges(q);
assert edges3.hasNext();
LOG.info(">>>> queryEdges(contribution): {}", edges3.hasNext());
while (edges3.hasNext()) {
LOG.info(">>>> queryEdges(contribution): {}", edges3.next());
}
}
// query by vertex label
vertices = graph.traversal().V().hasLabel("book");
size = vertices.toList().size();
assert size == 5;
LOG.info(">>>> query all books: size {}", size);
// query by vertex label and key-name
vertices = graph.traversal().V().hasLabel("person").has("age");
size = vertices.toList().size();
assert size == 5;
LOG.info(">>>> query all persons with age: size {}", size);
// query by vertex props
vertices = graph.traversal().V().hasLabel("person")
.has("city", "Taipei");
vertexList = vertices.toList();
assert vertexList.size() == 1;
LOG.info(">>>> query all persons in Taipei: {}", vertexList);
vertices = graph.traversal().V().hasLabel("person").has("age", 19);
vertexList = vertices.toList();
assert vertexList.size() == 1;
LOG.info(">>>> query all persons age==19: {}", vertexList);
vertices = graph.traversal().V().hasLabel("person")
.has("age", P.lt(19));
vertexList = vertices.toList();
assert vertexList.size() == 1;
assert vertexList.get(0).property("age").value().equals(3);
LOG.info(">>>> query all persons age<19: {}", vertexList);
String addr = "Bay Area";
vertices = graph.traversal().V().hasLabel("author")
.has("lived", Text.contains(addr));
vertexList = vertices.toList();
assert vertexList.size() == 1;
LOG.info(">>>> query all authors lived {}: {}", addr, vertexList);
}
public static void testRemove(final HugeGraph graph) {
// remove vertex (and its edges)
List<Vertex> vertices = graph.traversal().V().hasLabel("person")
.has("age", 19).toList();
assert vertices.size() == 1;
Vertex james = vertices.get(0);
Vertex book6 = graph.addVertex(T.label, "book", "name", "java-6");
james.addEdge("look", book6, "timestamp", "2017-5-2 12:00:08.0");
james.addEdge("look", book6, "timestamp", "2017-5-3 12:00:08.0");
graph.tx().commit();
assert graph.traversal().V(book6.id()).bothE().hasNext();
LOG.info(">>>> removing vertex: {}", james);
james.remove();
graph.tx().commit();
assert !graph.traversal().V(james.id()).hasNext();
assert !graph.traversal().V(book6.id()).bothE().hasNext();
// remove edge
VertexLabel author = graph.schema().getVertexLabel("author");
String authorId = String.format("%s:%s", author.id().asString(), "11");
EdgeLabel authored = graph.edgeLabel("authored");
VertexLabel book = graph.schema().getVertexLabel("book");
String book2Id = String.format("%s:%s", book.id().asString(), "java-2");
String edgeId = String.format("S%s>%s>%s>S%s",
authorId, authored.id(), "", book2Id);
List<Edge> edges = graph.traversal().E(edgeId).toList();
assert edges.size() == 1;
Edge edge = edges.get(0);
LOG.info(">>>> removing edge: {}", edge);
edge.remove();
graph.tx().commit();
assert !graph.traversal().E(edgeId).hasNext();
}
public static void testVariables(final HugeGraph graph) {
// variables test
Graph.Variables variables = graph.variables();
variables.set("owner", "zhangyi");
variables.set("time", 3);
variables.set("owner", "zhangyi1");
variables.keys();
graph.tx().commit();
variables.remove("time");
variables.get("time");
variables.get("owner");
variables.remove("owner");
variables.get("owner");
}
public static void testLeftIndexProcess(final HugeGraph graph) {
// test for process left index when addVertex to override prior vertex
graph.schema().indexLabel("personByCityAndAge").by("city", "age")
.onV("person").ifNotExist().create();
ExampleUtil.waitAllTaskDone(graph);
graph.addVertex(T.label, "person", "name", "Curry",
"city", "Hangzhou", "age", 27);
graph.addVertex(T.label, "person", "name", "Curry",
"city", "Shanghai", "age", 28);
graph.addVertex(T.label, "person", "name", "Curry",
"city", "Shanghai", "age", 30);
graph.tx().commit();
// set breakpoint here to see secondary_indexes and range_indexes table
List<Vertex> vertices = graph.traversal().V().has("age", 27)
.has("city", "Hangzhou").toList();
assert vertices.isEmpty();
// set breakpoint here to see secondary_indexes and range_indexes table
vertices = graph.traversal().V().has("age", 28).toList();
assert vertices.isEmpty();
// set breakpoint here to see secondary_indexes and range_indexes table
vertices = graph.traversal().V().has("city", "Hangzhou").toList();
assert vertices.isEmpty();
}
}