This example uses the TitanDB Getting Started guide as a template to demonstrate how to use HugeGraph. By comparing HugeGraph and TitanDB, you can understand the differences between them.
Both HugeGraph and TitanDB are graph databases based on the Apache TinkerPop3 framework. They both support the Gremlin graph query language and share many similarities in terms of usage and interfaces. However, HugeGraph is a completely new design and development, characterized by its clear code structure, richer features, and more user-friendly interfaces.
Compared to TitanDB, HugeGraph's main features are as follows:
This example uses the Property Graph Model to describe the relationships between characters in Greek mythology, also known as the character relationship graph. The specific relationships are shown in the diagram below.
In the diagram, circular nodes represent entities (Vertices), arrows represent relationships (Edges), and the content in the boxes represents attributes.
There are two types of vertices in this graph: characters and locations, as shown in the table below:
| Name | Type | Attributes |
|---|---|---|
| character | vertex | name,age,type |
| location | vertex | name |
There are six types of relationships: father, mother, brother, battled, lives, and pet. The details of these relationships are as follows:
| Name | Type | Source Vertex Label | Target Vertex Label | Attributes |
|---|---|---|---|---|
| father | edge | character | character | - |
| mother | edge | character | character | - |
| brother | edge | character | character | - |
| pet | edge | character | character | - |
| lives | edge | character | location | reason |
In HugeGraph, each edge label can only act on one pair of source and target vertex labels. In other words, if a relationship called “father” is defined in the graph to connect character to character, then “father” cannot be used to connect to other vertex labels.
Therefore, in this example, the original TitanDB's monster, god, human, and demigod are all represented using the same vertex label: character in HugeGraph, with an additional type attribute to indicate the type of character. The edge labels remain consistent with the original TitanDB. Of course, to satisfy the edge label constraints, adjustments can be made to the name of the edge label.
HugeGraph requires explicit schema creation, which involves creating PropertyKeys, VertexLabels, and EdgeLabels in sequence. If indexing is needed, IndexLabels must also be created.
schema = hugegraph.schema() schema.propertyKey("name").asText().ifNotExist().create() schema.propertyKey("age").asInt().ifNotExist().create() schema.propertyKey("time").asInt().ifNotExist().create() schema.propertyKey("reason").asText().ifNotExist().create() schema.propertyKey("type").asText().ifNotExist().create() schema.vertexLabel("character").properties("name", "age", "type").primaryKeys("name").nullableKeys("age").ifNotExist().create() schema.vertexLabel("location").properties("name").primaryKeys("name").ifNotExist().create() schema.edgeLabel("father").link("character", "character").ifNotExist().create() schema.edgeLabel("mother").link("character", "character").ifNotExist().create() schema.edgeLabel("battled").link("character", "character").properties("time").ifNotExist().create() schema.edgeLabel("lives").link("character", "location").properties("reason").nullableKeys("reason").ifNotExist().create() schema.edgeLabel("pet").link("character", "character").ifNotExist().create() schema.edgeLabel("brother").link("character", "character").ifNotExist().create()
// add vertices Vertex saturn = graph.addVertex(T.label, "character", "name", "saturn", "age", 10000, "type", "titan") Vertex sky = graph.addVertex(T.label, "location", "name", "sky") Vertex sea = graph.addVertex(T.label, "location", "name", "sea") Vertex jupiter = graph.addVertex(T.label, "character", "name", "jupiter", "age", 5000, "type", "god") Vertex neptune = graph.addVertex(T.label, "character", "name", "neptune", "age", 4500, "type", "god") Vertex hercules = graph.addVertex(T.label, "character", "name", "hercules", "age", 30, "type", "demigod") Vertex alcmene = graph.addVertex(T.label, "character", "name", "alcmene", "age", 45, "type", "human") Vertex pluto = graph.addVertex(T.label, "character", "name", "pluto", "age", 4000, "type", "god") Vertex nemean = graph.addVertex(T.label, "character", "name", "nemean", "type", "monster") Vertex hydra = graph.addVertex(T.label, "character", "name", "hydra", "type", "monster") Vertex cerberus = graph.addVertex(T.label, "character", "name", "cerberus", "type", "monster") Vertex tartarus = graph.addVertex(T.label, "location", "name", "tartarus") // add edges jupiter.addEdge("father", saturn) jupiter.addEdge("lives", sky, "reason", "loves fresh breezes") jupiter.addEdge("brother", neptune) jupiter.addEdge("brother", pluto) neptune.addEdge("lives", sea, "reason", "loves waves") neptune.addEdge("brother", jupiter) neptune.addEdge("brother", pluto) hercules.addEdge("father", jupiter) hercules.addEdge("mother", alcmene) hercules.addEdge("battled", nemean, "time", 1) hercules.addEdge("battled", hydra, "time", 2) hercules.addEdge("battled", cerberus, "time", 12) pluto.addEdge("brother", jupiter) pluto.addEdge("brother", neptune) pluto.addEdge("lives", tartarus, "reason", "no fear of death") pluto.addEdge("pet", cerberus) cerberus.addEdge("lives", tartarus)
HugeGraph by default automatically generates IDs. However, if a user specifies the primaryKeys field list for a VertexLabel through primaryKeys, the ID strategy for that VertexLabel will automatically switch to the primaryKeys strategy. Once the primaryKeys strategy is enabled, HugeGraph generates VertexId by concatenating vertexLabel+primaryKeys, which allows for automatic deduplication. Additionally, there is no need to create extra indexes to use the properties in primaryKeys for fast querying. For example, both “character” and “location” have the primaryKeys("name") attribute, so without creating additional indexes, vertices can be queried using g.V().hasLabel('character') .has('name','hercules').
1. Find the grandfather of hercules
g.V().hasLabel('character').has('name','hercules').out('father').out('father')
It can also be done using the repeat method:
g.V().hasLabel('character').has('name','hercules').repeat(__.out('father')).times(2)
2. Find the name of Hercules's father
g.V().hasLabel('character').has('name','hercules').out('father').value('name')
3. Find the characters with age > 100
g.V().hasLabel('character').has('age',gt(100))
4. Find who are pluto's cohabitants
g.V().hasLabel('character').has('name','pluto').out('lives').in('lives').values('name')
5. Find pluto can't be his own cohabitant
pluto = g.V().hasLabel('character').has('name', 'pluto') g.V(pluto).out('lives').in('lives').where(is(neq(pluto)).values('name') // use 'as' g.V().hasLabel('character').has('name', 'pluto').as('x').out('lives').in('lives').where(neq('x')).values('name')
6. Pluto's Brothers
pluto = g.V().hasLabel('character').has('name', 'pluto').next() // where do pluto's brothers live? g.V(pluto).out('brother').out('lives').values('name') // which brother lives in which place? g.V(pluto).out('brother').as('god').out('lives').as('place').select('god','place') // what is the name of the brother and the name of the place? g.V(pluto).out('brother').as('god').out('lives').as('place').select('god','place').by('name')
It is recommended to use HugeGraph-Hubble to execute the above code visually. Additionally, the code can be executed through various other methods such as HugeGraph-Client, HugeGraph-Api, GremlinConsole, and GremlinDriver.
HugeGraph currently supports Gremlin syntax, and users can implement various query requirements through Gremlin / REST-API.