Skip to content

Review queries

This page walks through the four queries in the example application. Each query demonstrates common patterns for traversing and analyzing graph data.

Query 1: Find transactions by user

This query finds all transactions initiated by Alice:

results = g.V().has("User", "name", "Alice") \
.out("owns") \
.out_e("Transaction") \
.as_("transaction") \
.in_v() \
.values("accountId") \
.as_("receiver") \
.select("transaction", "receiver") \
.by("amount") \
.by() \
.to_list()
for result in results:
print(f"Transaction Amount: {result['transaction']}, Receiver Account ID: {result['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") follows the “owns” edge to Alice’s account
  4. out_e("Transaction") traverses outgoing Transaction edges
  5. as_("transaction") labels these edges as “transaction” for later reference
  6. in_v() moves to the target vertices (receiving accounts)
  7. values("accountId") extracts the accountId property
  8. as_("receiver") labels these values as “receiver”
  9. select("transaction", "receiver") returns both labeled elements
  10. by("amount") specifies to return the amount property from the transaction edge
  11. by() specifies to return the accountId value as-is
  12. to_list() executes the query and returns results as a Python list

Output example:

Transaction Amount: 200, Receiver Account ID: A2
Transaction Amount: 456, Receiver Account ID: A3
Transaction Amount: 789, Receiver Account ID: A4

This pattern is useful for analyzing a specific user’s transaction history.

Query 2: Aggregate transaction amounts by account

This query calculates the total amount of outgoing transactions for each account:

results = g.V().has_label("Account") \
.group() \
.by("accountId") \
.by(__.out_e("Transaction").values("amount").sum_()) \
.to_list()
for result in results:
print(result)

How it works:

  1. V() starts at all vertices
  2. has_label("Account") filters to Account vertices only
  3. group() creates groups of vertices
  4. The first by("accountId") groups vertices by their accountId property
  5. The second by() clause defines what to compute for each group:
    • __.out_e("Transaction") traverses outgoing Transaction edges (the __ prefix indicates an anonymous traversal)
    • values("amount") extracts the amount property from each transaction
    • sum_() sums all amounts for that account
  6. to_list() returns the groups as a dictionary

Output example:

{'A1': 2345}
{'A2': 1876}
{'A3': 3012}
{'A4': 987}
{'A5': 2543}

This pattern is useful for computing aggregates like totals, averages, or counts grouped by a property.

Query 3: Find users who sent large transfers

This query finds all users who transferred more than 100 units to Alice:

results = g.V().has("User", "name", "Alice") \
.out("owns") \
.in_e("Transaction") \
.has("amount", P.gte(100)) \
.out_v() \
.in_("owns") \
.value_map("name") \
.to_list()
for result in results:
print(f"User: {result}")

How it works:

  1. V() starts at all vertices
  2. has("User", "name", "Alice") finds Alice’s User vertex
  3. out("owns") follows the “owns” edge to Alice’s account
  4. in_e("Transaction") traverses incoming Transaction edges (money coming in)
  5. has("amount", P.gte(100)) filters to transactions with amount greater than or equal to 100
  6. out_v() moves to the source vertices of those transactions (sending accounts)
  7. in_("owns") follows “owns” edges backwards to find the owning users
  8. value_map("name") returns a map of properties for each user (in this case, just the name)
  9. to_list() returns all matching users

Output example:

User: {'name': ['Bob']}
User: {'name': ['Charlie']}
User: {'name': ['Diana']}

Note that value_map() returns property values as lists because vertices can have multiple values for the same property key. To get a single value, you can use values("name") instead.

The P.gte() predicate (greater than or equal) is one of many comparison operators available:

  • P.eq() - equals
  • P.neq() - not equals
  • P.lt() - less than
  • P.lte() - less than or equal
  • P.gt() - greater than
  • P.gte() - greater than or equal
  • P.between() - within a range

This pattern is useful for fraud detection, identifying suspicious transaction patterns, or finding high-value customers.

Query 4: Retrieve user properties

This query retrieves all properties for Bob:

bob_properties = g.V().has("User", "name", "Bob").value_map().next()
for key, value in bob_properties.items():
print(f"{key}: {value[0]}")

How it works:

  1. V() starts at all vertices
  2. has("User", "name", "Bob") filters to Bob’s User vertex
  3. value_map() returns a dictionary of all properties on the vertex
  4. next() executes the query and returns the first (and only) result

Output example:

userId: U2
name: Bob
age: 35

The value_map() method returns property values as lists. The code accesses value[0] to extract the first (and typically only) value for each property.

If you only need specific properties, you can pass them as arguments:

bob_name_and_age = g.V().has("User", "name", "Bob").value_map("name", "age").next()

This pattern is useful for displaying detailed information about a specific entity in your application.

Key Gremlin concepts

These queries demonstrate several important Gremlin concepts:

Traversal steps:

  • V() - start at vertices
  • E() - start at edges
  • has(), has_label() - filter by properties or labels
  • out(), in_() - traverse edges to adjacent vertices
  • out_e(), in_e() - traverse to adjacent edges
  • out_v(), in_v() - traverse from edges to vertices
  • values() - extract property values
  • value_map() - extract all properties as a map

Terminal steps:

  • next() - return the next result
  • to_list() - return all results as a list
  • iterate() - execute without returning results

Modulation:

  • as_() - label a step for later reference
  • select() - return labeled elements
  • by() - specify how to project or sort elements

Predicates:

  • P.eq(), P.gte(), P.between() - comparison operators

Anonymous traversals:

  • __ - start a nested traversal within another step

Common patterns

The queries demonstrate three common patterns:

  1. Path traversal: Start at a vertex, follow edges to related vertices (Query 1 and 3).
  2. Aggregation: Group vertices or edges and compute summary statistics (Query 2).
  3. Property extraction: Retrieve detailed attributes of specific entities (Query 4).

These patterns form the foundation for more complex graph queries in real applications.

Clean up

After running the queries, the example drops all vertices and edges:

g.V().drop().iterate()

The drop() step removes vertices and edges from the graph. This cleans up the data so you can run the example multiple times without creating duplicate entries.

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?