Skip to main content

Gremlin

RushDB accepts Apache TinkerPop Gremlin traversals written as text strings. Traversals read and write the same graph that SQL, Cypher, and the native API use. This page covers the supported steps, how records map to vertices, and the parts of TinkerPop that are not exposed. It is for developers with existing Gremlin traversals or TinkerPop experience.

PropertyValue
StatusStable (text traversal and GraphSON 3 bytecode)
EnabledBy default (languages.gremlin: true); a --languages list must name gremlin to keep it
Wire idgremlin
ProfileApache TinkerPop Gremlin traversal profile (text and GraphSON 3 bytecode)
ImplementationGrafeo graph planner with a gremlin-rs grammar
Accessread and write
Parametersnamed ($name)
TransportsProtocol v1 (HTTP, gRPC)

Data model mapping​

Gremlin conceptRushDB
VertexA record
Vertex labelThe record's single primary label
EdgeA relationship
Edge labelThe relationship type
PropertyA record or relationship property
Graph traversal source gThe request's tenant

Reading​

Traversals are sent as strings with query.statement:

{
"protocolVersion": 1,
"operation": {
"kind": "query",
"query": {
"kind": "statement",
"language": "gremlin",
"statement": "g.V().hasLabel('FACTION').values('name')"
}
}
}

Tested read steps:

g.V().hasLabel('Person').values('name')
g.V().hasLabel('Person').has('age', gt(30)).values('name')
g.V().hasLabel('Person').has('name', 'Alice').out('KNOWS').values('name')
g.V().hasLabel('Person').values('name').order().range(1, 2)
g.V().hasLabel('Person').count()

Named parameters are bound by the engine:

{
"kind": "statement",
"language": "gremlin",
"statement": "g.V().hasLabel('Person').has('name', $name).values('age')",
"parameters": { "name": "Alice" }
}

Writing​

Send writes with mutate.statement. Each traversal is published as one atomic commit.

Add a vertex:

g.addV('FACTION').property('name', 'Rebel Alliance')

Add an edge between existing vertices:

g.V().has('name', 'Alice').as('a').V().has('name', 'Bob').addE('LIKES').from('a').property('weight', 3)

Update a property and drop elements:

g.V().hasLabel('Person').has('name', 'Alice').property('age', 36)
g.V().hasLabel('Person').has('name', 'Carol').drop()
g.E().hasLabel('LIKES').drop()

Gremlin writes can also be staged in a multi-request transaction with a statement mutation ("language": "gremlin").

Bytecode​

TinkerPop language variants (gremlin-python, gremlin-javascript, Gremlin.Net, the Java driver) build a traversal as bytecode. Serialize it as GraphSON 3 and send it with query.gremlinBytecode (reads) or mutate.gremlinBytecode (writes); RushDB translates it into the equivalent text traversal and runs it exactly as one:

{
"kind": "query",
"query": {
"kind": "gremlinBytecode",
"bytecode": {"@type": "g:Bytecode", "@value": {"step": [
["V"], ["hasLabel", "person"],
["has", "age", {"@type": "g:P", "@value": {"predicate": "gt", "value": 28}}],
["values", "name"]
]}}
}
}

The traversals RushDB's profile covers are listed in crates/rushdb-language/conformance/gremlin-profile-v1.json; each runs on the engine in CI and is checked against the official TinkerPop grammar. Anonymous traversals are written as bare chained steps (where(out('created'))).

Accepted argument types: JSON scalars, g:Int32, g:Int64, g:Float, g:Double, g:List, g:Set, g:Map, g:P and g:TextP (including and, or, not), the g:T, g:Order, g:Scope, g:Column, g:Direction, g:Pop and g:Cardinality enums, and nested g:Bytecode (anonymous traversals). Lambdas, traversal strategies and other source instructions, and any other type are refused with unsupported.

Limitations​

The capability profile advertises these limitations:

LimitationMeaning
graphBinaryNotExposedGraphBinary serialization and a Gremlin Server endpoint are not provided, so TinkerPop drivers cannot connect directly. Send their traversal bytecode as GraphSON 3 through Protocol v1 (see Bytecode), or traversal strings.
singlePrimaryLabelPerRecordA vertex has exactly one label.
statementLabelMutationUnavailableTraversals cannot change a vertex's label. Use the native retypeRecord mutation.

Also:

  • A write holds only the vertices and edges it creates or changes, refused above 100,000 records or 64 MiB of them (not the tenant's size).
  • Results are materialized; use range() to page.
  • A write that changes nothing succeeds with affected: 0 and commits nothing.
  • Steps other than those shown above may parse but are not covered by the test profile. Unsupported syntax fails with unsupported; it is never silently ignored.

See also​