Skip to content

Latest commit

 

History

History

cypher-gremlin-server-client

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Cypher Client for Gremlin Server

Maven Central

This is a convenience Gremlin Server client for Java that can send queries via a Gremlin Client instance:

  • to a remote Gremlin Server with Cypher plugin,
  • with client-side translation: to a Gremlin Server-based database, Amazon Neptune, or Azure Cosmos DB.

Getting Started

To add a dependency using Maven:

<dependency>
    <groupId>org.opencypher.gremlin</groupId>
    <artifactId>cypher-gremlin-server-client</artifactId>
    <version>1.0.4</version>
</dependency>

To add a dependency using Gradle:

dependencies {
  compile 'org.opencypher.gremlin:cypher-gremlin-server-client:1.0.4'
}

You can also build the snapshot from source.

Usage

To send Cypher queries to a Cypher-enabled Gremlin Server and get Cypher-style results:

Cluster cluster = Cluster.open(configuration);
Client gremlinClient = cluster.connect();
CypherGremlinClient cypherGremlinClient = CypherGremlinClient.plugin(gremlinClient);
String cypher = "MATCH (p:person) WHERE p.age > 25 RETURN p.name";
CypherResultSet resultSet = cypherGremlinClient.submit(cypher);
List<Map<String, Object>> results = resultSet.all();

Result sets can be consumed in various ways (all share the same iterator, so pick one):

List<Map<String, Object>> list = cypherGremlinClient.submit(cypher).all(); // as a list
Stream<Map<String, Object>> stream = cypherGremlinClient.submit(cypher).stream(); // as a stream
Iterator<Map<String, Object>> iterator = cypherGremlinClient.submit(cypher).iterator(); // as an iterator
Iterable<Map<String, Object>> iterable = cypherGremlinClient.submit(cypher); // also an iterable

Queries can be submitted asynchronously:

String cypher = "MATCH (p:person) WHERE p.age > 25 RETURN p.name";
CompletableFuture<CypherResultSet> future = cypherGremlinClient.submitAsync(cypher);
future
    .thenApply(CypherResultSet::all)
    .thenAccept(resultSet -> {
        // ...
    });

If the target Gremlin Server does not have the Cypher plugin installed, translation can be done on the client's thread:

CypherGremlinClient cypherGremlinClient = CypherGremlinClient.translating(gremlinClient);

It is possible to configure statement parameters and timeout:

CypherGremlinClient client = CypherGremlinClient.plugin(gremlinClient);

List<Map<String, Object>> results = client.statement("MATCH (n) WHERE n.name=$p1 AND n.age=$p2 RETURN n")
    .addParameter("p1", "marko")
    .addParameter("p2", 29L)
    .withTimeout(30, TimeUnit.SECONDS)
    .submit()
    .get().all();

Azure Cosmos DB

A translating client for Azure Cosmos DB can be configured like so:

CypherGremlinClient cypherGremlinClient = CypherGremlinClient.retrieving(
    gremlinClient,
    TranslatorFlavor.cosmosDb()
);

Amazon Neptune

A translating client for Amazon Neptune can be configured like so:

CypherGremlinClient cypherGremlinClient = CypherGremlinClient.translating(
    gremlinClient,
    () -> Translator.builder()
        .gremlinGroovy()
        .inlineParameters()
        .enableMultipleLabels()
        .build(TranslatorFlavor.neptune())
);

In-memory Client

You can also execute Cypher directly against a GraphTraversalSource:

TinkerGraph graph = TinkerFactory.createModern();
GraphTraversalSource traversal = graph.traversal();
CypherGremlinClient cypherGremlinClient = CypherGremlinClient.inMemory(traversal);
String cypher = "MATCH (p:person) WHERE p.age > 25 RETURN p.name";
List<Map<String, Object>> results = cypherGremlinClient.submit(cypher).all();

Consult the Javadoc for more information.

Neo4j driver-like API

If you want to use a Neo4j driver-like API, take a look at the Cypher Gremlin Neo4j Driver.

Cypher Traversal Source

With CypherTraversalSource its possible to combine Cypher and Gremlin in single query. Traversal can start with cypher step that allows to run Cypher query (which will be translated to Gremlin) then continue traversal using other Gremlin steps. Note that cypher step returns list of maps, corresponding to rows and named columns. To continue traversal with other Gremlin steps, use select step:

CypherTraversalSource g = graph.traversal(CypherTraversalSource.class);

GraphTraversal<Map<String, Object>, String> query = g
    .cypher("MATCH (n) RETURN n")
    .select("n")
    .outE()
    .label()
    .dedup();

This approach can be used for remote databases using withRemote. Translation could be adapted for specific Gremlin implementation by passing Flavor or enabling Gremlin Extensions for Cypher:

CypherTraversalSource g = AnonymousTraversalSource
    .traversal(CypherTraversalSource.class)
    .withRemote(PATH_TO_REMOTE_PROPERTIES);

GraphTraversal<Map<String, Object>, String> traversal = g
    .cypher("MATCH (n) RETURN n", "cosmosdb")
    .select("n")
    .outE()
    .label()
    .dedup();

Note that Cypher query may return null values, represented by string constant.

Gremlin function

Experimental gremlin Cypher function that allows including Gremlin steps in translated query. Note that currently function should be enabled explicitly.

CypherGremlinClient cypherGremlinClient = CypherGremlinClient.translating(
    gremlinClient,
    () -> Translator.builder()
        .gremlinGroovy()
        .enableCypherExtensions()
        .enable(TranslatorFeature.EXPERIMENTAL_GREMLIN_FUNCTION)
        .build()
);

List<Map<String, Object>> results = cypherGremlinClient.submit(
    "MATCH (n:person {name: 'marko'}) " +
        "RETURN gremlin(\"select('n').outE().label()\") as r").all();

For Gremlin Server set translatorFeatures: "+multiple_labels" in opProcessor configuration