Fluent traversals can be wrapped into a FluentGraphStatement and passed to the session:
// A "dummy", non-connected traversal source that is not meant to be iterated directly, but instead // serves as the basis to build fluent statements: import static com.datastax.dse.driver.api.core.graph.DseGraph.g; GraphTraversal<Vertex, Vertex> traversal = g.V().has("name", "marko"); FluentGraphStatement statement = FluentGraphStatement.newInstance(traversal); GraphResultSet result = session.execute(statement); for (GraphNode node : result) { System.out.println(node.asVertex()); }
As shown above, FluentGraphStatement.newInstance creates a statement from a traversal directly.
The default implementation returned by the driver is immutable; if you call additional methods on the statement -- for example to set options -- each method call will create a new copy:
FluentGraphStatement statement = FluentGraphStatement.newInstance(traversal); FluentGraphStatement statement2 = statement.setTimeout(Duration.ofSeconds(10)); assert statement2 != statement;
Immutability is good because it makes statements inherently thread-safe: you can share them in your application and access them concurrently without any risk.
On the other hand, it means a lot of intermediary copies if you often call methods on your statements. Modern VMs are normally good at dealing with such short-lived objects, but if you're worried about the performance impact, consider using a builder instead.
Note: contrary to driver statements, Tinkerpop's GraphTraversal
is mutable and therefore not thread-safe. This is fine if you just wrap a traversal into a statement and never modify it afterwards, but be careful not to share traversals and modify them concurrently.
Instead of creating a statement directly, you can pass your traversal to FluentGraphStatement.builder, chain method calls to set options, and finally call build()
:
FluentGraphStatement statement1 = FluentGraphStatement.builder(traversal) .withTimeout(Duration.ofSeconds(10)) .withIdempotence(true) .build();
The builder implementation is mutable: every method call returns the same object, only one builder instance will be created no matter how many methods you call on it. As a consequence, the builder object is not thread-safe.
You can also initialize a builder from an existing statement: it will inherit all of its options.
FluentGraphStatement statement2 = FluentGraphStatement.builder(statement1).withTimeout(Duration.ofSeconds(20)).build(); assert statement2.getTraversal().equals(statement1.getTraversal()); assert statement2.getTimeout().equals(Duration.ofSeconds(20)); // overridden by the builder assert statement2.isIdempotent(); // because statement1 was
BatchGraphStatement allows you to execute multiple mutating traversals in the same transaction. Like other types of statements, it is immutable and thread-safe, and can be created either with a factory method or a builder:
GraphTraversal<Vertex, Vertex> traversal1 = g.addV("person").property("name", "batch1").property("age", 1); GraphTraversal<Vertex, Vertex> traversal2 = g.addV("person").property("name", "batch2").property("age", 2); // Each method call creates a copy: BatchGraphStatement batch1 = BatchGraphStatement.newInstance() .addTraversal(traversal1) .addTraversal(traversal2); // Uses a single, mutable builder instance: BatchGraphStatement batch2 = BatchGraphStatement.builder() .addTraversal(traversal1) .addTraversal(traversal2) .build();
Traversal batches are only available with DSE 6.0 or above.
At the time of writing (DSE 6.0), prepared graph statements are not supported yet; they will be added in a future version.
See also the parent page for topics common to all fluent traversals.