Gremlin
ArcadeDB supports Gremlin 3.7.x as query engine and in the Gremlin Server. You can execute a gremlin query from pretty much everywhere.
If you’re using ArcadeDB as embedded, please add the dependency to the arcadedb-gremlin library.
If you’re using Maven include this dependency in your pom.xml file.
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-gremlin</artifactId>
<version>26.5.1</version>
</dependency>
|
CRITICAL SECURITY NOTICE: ArcadeDB uses the secure Java Gremlin engine by default (from version 25.12.1). DO NOT use the Groovy engine ( See Gremlin Security for complete details about this vulnerability. |
Gremlin from Java API
In order to execute a Gremlin query, you need to include the relevant jars, i.e. the apache-tinkerpop-gremlin-server libraries, plus gremlin-groovy, plus opencypher-util-9.0, in your class path.
To execute a Gremlin query, use "gremlin" as first parameter in the query method.
Example:
ResultSet result = database.query("gremlin", "g.V().has('name','Michelle').has('lastName','Besso').out('IsFriendOf')");
If you’re application is mostly based on Gremlin, the best way is to use the ArcadeGraph class as an entrypoint. Example:
try (final ArcadeGraph graph = ArcadeGraph.open("./databases/graph")) {
Vertex michelleFriend = graph.traversal().V().has("name","Michelle").has("lastName","Besso").out("IsFriendOf").next();
}
You can also work with a remote ArcadeDB Server:
try( RemoteDatabase database = new RemoteDatabase("127.0.0.1", 2480, "graph", "root", "playwithdata") ){
try (final ArcadeGraph graph = ArcadeGraph.open(database)) {
Vertex michelleFriend = graph.traversal().V().has("name","Michelle").has("lastName","Besso").out("IsFriendOf").next();
}
}
Since a RemoteDatabase instance cannot be shared between threads, if your application is multi-threads, you can use the ArcadeGraphFactory to acquire ArcadeGraph instances from a pool. Example:
try (ArcadeGraphFactory pool = ArcadeGraphFactory.withRemote("127.0.0.1", 2480, "mydb", "root", "playwithdata")) {
try( ArcadeGraph graph = pool.get() ){
// DO SOMETHING WITH ARCADE GRAPH
}
}
Remember to call ArcadeGraph.close() to release the ArcadeGraph instance back into the pool. ArcadeGraph implements Closable, so you can just use it in a try block like in the example above.
|
Gremlin through Postgres Driver
You can execute a Gremlin query against ArcadeDB server by using the Postgres driver and prefixing the query with {gremlin}.
Example:
"{gremlin} g.V().has('name','Michelle').has('lastName','Besso').out('IsFriendOf')"
ArcadeDB server will execute the query g.V().has('name','Michelle').has('lastName','Besso').out('IsFriendOf') using the Gremlin query language.
Gremlin through HTTP/JSON
You can execute a Gremlin query against ArcadeDB server by using HTTP/JSON API. Example of executing an idempotent query with HTTP GET command:
curl "http://localhost:2480/query/graph/gremlin/g.V().has('name','Michelle').has('lastName','Besso').out('IsFriendOf')"
Example of executing a non-idempotent query (updates the database):
curl -X POST "http://localhost:2480/command/graph" -d "{'language': 'gremlin', 'command': 'g.V().has(\"name\",\"Michelle\").has(\"lastName\",\"Besso\").out(\"IsFriendOf\")'}"
Use the Gremlin Server
Apache TinkerPop Gremlin provides a standalone server to allow remote access with a Gremlin client. In order to use the Gremlin Server with ArcadeDB, you have to enable it from ArcadeDB’s server plugin system:
~/arcadedb $ bin/server.sh -Darcadedb.server.plugins="GremlinServer:com.arcadedb.server.gremlin.GremlinServerPlugin"
If you’re using MS Windows OS, replace bin/server.sh with bin\server.bat.
At startup, the Gremlin Server plugin looks for the file config/gremlin-server.yaml under ArcadeDB path.
If the file is present, the Gremlin Server will be configured with the settings contained in the YAML file, otherwise the default configuration will be used.
You can also override single configuration settings by using ArcadeDB’s settings and prefixing the configuration key with gremlin..
All the configuration settings with such a prefix will be passed to the Gremlin Server plugin.
Multi-Database Support (v26.2.1+)
Starting from version 26.2.1, ArcadeDB’s Gremlin Server includes ArcadeGraphManager, a custom implementation of TinkerPop’s GraphManager interface that provides dynamic, on-demand registration of databases as Gremlin graphs.
Key Features:
-
Automatic Registration: When a Gremlin client requests a graph/traversal source by database name,
ArcadeGraphManagerautomatically registers it if the database exists in ArcadeDB Server -
Multi-Database Access: Access any database on the server through Gremlin without static configuration
-
The
gAlias: The standardgalias automatically maps to the default database ("graph" if it exists, otherwise the first available database)
How It Works:
Instead of static graph configuration in YAML files, databases are registered dynamically when first accessed. Each database name becomes a valid traversal source alias:
// Connect to a specific database using its name as the alias
var cluster = Cluster.build()
.port(8182)
.addContactPoint("localhost")
.credentials("root", "password")
.create();
// Access database "mydb" - registered automatically on first access
var g = traversal().withRemote(DriverRemoteConnection.using(cluster, "mydb"));
// Or use the standard "g" alias for the default database
var gDefault = traversal().withRemote(DriverRemoteConnection.using(cluster, "g"));
Script-Based Queries:
For script-based Gremlin queries (e.g., via client.submit()), the g variable is automatically bound to the default database:
Client client = cluster.connect();
// The "g" variable is automatically available
ResultSet results = client.submit("g.V().hasLabel('Person').count()");
Benefits:
-
No need to manually configure graphs in
gremlin-server.yamlorgremlin-server.groovy -
Supports ArcadeDB’s multi-tenant architecture where a single server hosts multiple databases
-
Each database is isolated and accessed independently through its name
-
Reduces configuration complexity for deployments with many databases
Legacy static configuration via gremlin-server.yaml graphs section is no longer required. All databases are available automatically
|
Migration Guide (v26.2.1)
If you are upgrading from a version prior to 26.2.1, here are the key changes to be aware of:
What Changed:
-
Graph Registration: Graphs are now registered dynamically by
ArcadeGraphManagerinstead of statically in configuration files -
Configuration Files: The
graphs:section ingremlin-server.yamlis no longer required -
The
graphBinding: The internalgraphvariable is now managed byArcadeGraphManagerto properly support TinkerPop sessions and transactions
Backward Compatibility:
-
Existing Gremlin queries continue to work without modification
-
The
galias still works and maps to the default database -
Script-based queries using
gare fully supported -
Bytecode-based queries work with any database name as the alias
Configuration Migration:
If you had custom gremlin-server.yaml configuration:
# OLD configuration (no longer needed)
graphs:
graph: conf/arcadedb.properties
This static configuration is now optional. ArcadeGraphManager will automatically register any database when it is first accessed. You can safely remove the graphs: section.
Custom gremlin-server.groovy:
If you customized gremlin-server.groovy, ensure you are NOT overwriting the graph binding:
// CORRECT: Only define the traversal source 'g'
globals << [g : traversal().withEmbedded(graph)]
// WRONG: Do NOT overwrite 'graph' - this breaks session support
// globals << [graph : traversal().withEmbedded(graph)] // DON'T DO THIS
The graph variable must remain a Graph object (not a GraphTraversalSource) for TinkerPop’s SessionOpProcessor to work correctly with transactions.
Accessing Multiple Databases:
To access a specific database, use the database name as the traversal source alias:
// Before v26.2.1 - required manual configuration
// Now - just use the database name directly
var g = traversal().withRemote(DriverRemoteConnection.using(cluster, "customers"));
var g2 = traversal().withRemote(DriverRemoteConnection.using(cluster, "products"));
Transactions via Remote Driver:
Gremlin transactions now work correctly via the remote driver:
GraphTraversalSource g = traversal().withRemote(
DriverRemoteConnection.using(cluster, "mydb"));
Transaction tx = g.tx();
GraphTraversalSource gtx = tx.begin();
try {
gtx.addV("Person").property("name", "Alice").iterate();
tx.commit();
} catch (Exception e) {
tx.rollback();
}
Docker Example:
Start the Gremlin Server with the OpenBeer dataset imported as a database named openbeer:
docker run -d --name arcadeDB -p 2424:2424 -p 2480:2480 -p 8182:8182 \
--env JAVA_OPTS="-Darcadedb.server.rootPassword=playwithdata \
-Darcadedb.server.defaultDatabases=openbeer[root]{import:https://github.com/ArcadeData/arcadedb-datasets/raw/main/orientdb/OpenBeer.gz} \
-Darcadedb.server.plugins=GremlinServer:com.arcadedb.server.gremlin.GremlinServerPlugin " \
arcadedata/arcadedb:latest
When running ArcadeDB with Docker, expose port 8182 for Gremlin Server and use -e to pass JVM settings.
|
Connecting to the Gremlin Server:
var cluster = Cluster.build()
.port(8182)
.addContactPoint("localhost")
.credentials("root", "password")
.create();
// Connect using the database name as the alias
var g = traversal().withRemote(DriverRemoteConnection.using(cluster, "openbeer"));
// Or use "g" for the default database
var gDefault = traversal().withRemote(DriverRemoteConnection.using(cluster, "g"));
Known Limitations with the Gremlin Implementation
-
ArcadeDB automatically handles the conversion between compatible types, such as strings and numbers when possible. Gremlin does not. So if you define a schema with the ArcadeDB API and then you use Gremlin for a traversal, ensure you’re using the same type you defined in the schema. For example, if you define a property "id" to be a string, and then you’re executing traversal by using integers for the ids, the result could be unpredictable.
-
ArcadeDB’s Gremlin implementation always tries to optimize the Gremlin traversal by using ArcadeDB’s internal query. While this is easy with simple traversal using
.has()and.hasLabel(), it is unable to optimize more complex traversal withselect()andwhere(). Instead of executing an optimized query, it could result in a full scan of the type, leaving to Gremlin the filtering. While the result of the traversal is still correct, the performance would be heavily impacted. Please consider using ArcadeDB’s SQL or Native Select for the best performance with complex traversals.
For more information about Gremlin:
Recommended Tools with Gremlin
If you’re using Gremlin with ArcadeDB, check out gdotv graph tool. It is compatible with ArcadeDB and provides a powerful visual debugger, advanced graph analytics, and much more.
