Skip to content

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

  1. V() starts at all vertices in the graph
  2. has("User", "name", "Alice") filters to the User vertex with name “Alice”
  3. out("owns") traverses outgoing “owns” edges to reach Alice’s account
  4. outE("Transaction") traverses outgoing Transaction edges
  5. as("transaction") labels the edge for later reference
  6. inV() moves to the receiving account vertex
  7. values("accountId") extracts the accountId property
  8. as("receiver") labels this value for later reference
  9. select("transaction", "receiver") retrieves both labeled items
  10. by("amount") projects the transaction’s amount property
  11. by() projects the receiver value as-is
  12. forEachRemaining() iterates over results and prints them

Output

QUERY 1: Transactions initiated by Alice:
Transaction Amount: 200, Receiver Account ID: A2
Transaction Amount: 722, Receiver Account ID: A1
Transaction Amount: 282, Receiver Account ID: A5

This 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

  1. V().hasLabel("Account") starts at all Account vertices
  2. group() creates groups of vertices
  3. by("accountId") groups by the accountId property (the key)
  4. The second by() defines how to aggregate each group (the value):
    • __.outE("Transaction") starts an anonymous traversal from each account
    • values("amount") extracts the amount property from each edge
    • sum() adds up all the amounts
  5. 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=2345
A2=1876
A3=3012
A4=987
A5=2543

This 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

  1. V().has("User", "name", "Alice") finds Alice’s User vertex
  2. out("owns") traverses to Alice’s account
  3. inE("Transaction") traverses incoming Transaction edges (transfers to Alice)
  4. has("amount", P.gte(100)) filters to transactions with amount greater than or equal to 100
  5. outV() moves to the sending account vertex
  6. in("owns") traverses incoming “owns” edges to find the account owner
  7. valueMap("name") extracts the name property as a map
  8. forEachRemaining() 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

  1. V().has("User", "name", "Bob") finds Bob’s User vertex
  2. next() executes the traversal and returns the first result
  3. bob.properties() retrieves an iterator over all properties
  4. forEachRemaining() iterates over properties
  5. property.key() gets the property name
  6. property.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 : U2
name : Bob
age : 35

This 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() and outE() follow outgoing edges
  • in() and inE() follow incoming edges
  • outV() moves to an edge’s source vertex
  • inV() moves to an edge’s target vertex

Filtering

  • has() filters vertices or edges by property values
  • hasLabel() filters by label
  • Predicates like P.gte(), P.lt(), P.between() enable complex comparisons

Projection and selection

  • values() extracts property values
  • valueMap() returns properties as a map
  • select() retrieves multiple labeled items
  • by() modulates how to project selected items

Aggregation

  • group() creates groups of elements
  • sum() adds numeric values
  • by() defines grouping keys and aggregation functions

Terminal steps

  • next() returns a single result
  • iterate() executes without returning results (side effects only)
  • forEachRemaining() processes all results with a consumer function
Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?