Review queries
This page walks through the four queries in the example application. Each query demonstrates a different Gremlin pattern for analyzing transaction data.
Query 1: Find transactions by user
This query finds all transactions initiated by a specific user (Alice):
System.out.println("\nQUERY 1: Transactions initiated by Alice:");g.V().has("User", "name", "Alice") .out("owns") .outE("Transaction") .as("transaction") .inV() .values("accountId") .as("receiver") .select("transaction", "receiver") .by("amount") .by() .forEachRemaining(result -> System.out.println("Transaction Amount: " + result.get("transaction") + ", Receiver Account ID: " + result.get("receiver")));How it works
V()starts at all vertices in the graphhas("User", "name", "Alice")filters to the User vertex with name “Alice”out("owns")traverses outgoing “owns” edges to reach Alice’s accountoutE("Transaction")traverses outgoing Transaction edgesas("transaction")labels the edge for later referenceinV()moves to the receiving account vertexvalues("accountId")extracts the accountId propertyas("receiver")labels this value for later referenceselect("transaction", "receiver")retrieves both labeled itemsby("amount")projects the transaction’s amount propertyby()projects the receiver value as-isforEachRemaining()iterates over results and prints them
Output
QUERY 1: Transactions initiated by Alice:Transaction Amount: 200, Receiver Account ID: A2Transaction Amount: 722, Receiver Account ID: A1Transaction Amount: 282, Receiver Account ID: A5This query is useful for tracking a user’s spending patterns or detecting unusual transaction activity.
Query 2: Aggregate transaction amounts by account
This query calculates the total amount of outgoing transactions for each account:
System.out.println("\nQUERY 2: Total transaction amounts initiated by users:");g.V().hasLabel("Account") .group() .by("accountId") .by( __.outE("Transaction") .values("amount") .sum() ) .forEachRemaining(System.out::println);How it works
V().hasLabel("Account")starts at all Account verticesgroup()creates groups of verticesby("accountId")groups by the accountId property (the key)- The second
by()defines how to aggregate each group (the value):__.outE("Transaction")starts an anonymous traversal from each accountvalues("amount")extracts the amount property from each edgesum()adds up all the amounts
forEachRemaining()prints each group and its total
The double underscore __ introduces an anonymous traversal, which is a nested traversal that starts from the current position without affecting the outer traversal’s state.
Output
QUERY 2: Total transaction amounts initiated by users:A1=2345A2=1876A3=3012A4=987A5=2543This query is useful for generating financial reports or detecting accounts with unusually high transaction volumes.
Query 3: Find users who sent large transfers
This query identifies users who transferred more than 100 currency units to Alice:
System.out.println("\nQUERY 3: Users who transferred greater than 100 to Alice:");g.V().has("User", "name", "Alice") .out("owns") .inE("Transaction") .has("amount", P.gte(100)) .outV() .in("owns") .valueMap("name") .forEachRemaining(result -> System.out.println("User: " + result));How it works
V().has("User", "name", "Alice")finds Alice’s User vertexout("owns")traverses to Alice’s accountinE("Transaction")traverses incoming Transaction edges (transfers to Alice)has("amount", P.gte(100))filters to transactions with amount greater than or equal to 100outV()moves to the sending account vertexin("owns")traverses incoming “owns” edges to find the account ownervalueMap("name")extracts the name property as a mapforEachRemaining()prints each user’s name
The P.gte(100) predicate uses TinkerPop’s predicate API. Other predicates include P.lt() (less than), P.between(), and P.eq() (equals).
Output
QUERY 3: Users who transferred greater than 100 to Alice:User: {name=[Bob]}User: {name=[Charlie]}User: {name=[Diana]}This query pattern is useful for fraud detection, identifying potential money laundering, or analyzing customer relationships.
Query 4: Retrieve all properties of a vertex
This query retrieves all properties of a specific user:
System.out.println("\nQUERY 4: Properties of Bob:");final Vertex bob = g.V().has("User", "name", "Bob").next();bob.properties().forEachRemaining(property -> System.out.println(property.key() + " : " + property.value()));How it works
V().has("User", "name", "Bob")finds Bob’s User vertexnext()executes the traversal and returns the first resultbob.properties()retrieves an iterator over all propertiesforEachRemaining()iterates over propertiesproperty.key()gets the property nameproperty.value()gets the property value
Unlike the previous queries that use the fluent traversal API throughout, this query retrieves a Vertex object and then uses Java’s object-oriented API to access its properties.
Output
QUERY 4: Properties of Bob:userId : U2name : Bobage : 35This approach is useful when you need to work with graph elements as Java objects rather than continuing a traversal chain.
Common Gremlin patterns
The example queries illustrate several important Gremlin patterns:
Traversal direction
out()andoutE()follow outgoing edgesin()andinE()follow incoming edgesoutV()moves to an edge’s source vertexinV()moves to an edge’s target vertex
Filtering
has()filters vertices or edges by property valueshasLabel()filters by label- Predicates like
P.gte(),P.lt(),P.between()enable complex comparisons
Projection and selection
values()extracts property valuesvalueMap()returns properties as a mapselect()retrieves multiple labeled itemsby()modulates how to project selected items
Aggregation
group()creates groups of elementssum()adds numeric valuesby()defines grouping keys and aggregation functions
Terminal steps
next()returns a single resultiterate()executes without returning results (side effects only)forEachRemaining()processes all results with a consumer function