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:
V()starts at all vertices in the graphhas("User", "name", "Alice")filters to the User vertex with name “Alice”out("owns")follows the “owns” edge to Alice’s accountout_e("Transaction")traverses outgoing Transaction edgesas_("transaction")labels these edges as “transaction” for later referencein_v()moves to the target vertices (receiving accounts)values("accountId")extracts the accountId propertyas_("receiver")labels these values as “receiver”select("transaction", "receiver")returns both labeled elementsby("amount")specifies to return the amount property from the transaction edgeby()specifies to return the accountId value as-isto_list()executes the query and returns results as a Python list
Output example:
Transaction Amount: 200, Receiver Account ID: A2Transaction Amount: 456, Receiver Account ID: A3Transaction Amount: 789, Receiver Account ID: A4This 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:
V()starts at all verticeshas_label("Account")filters to Account vertices onlygroup()creates groups of vertices- The first
by("accountId")groups vertices by their accountId property - 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 transactionsum_()sums all amounts for that account
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:
V()starts at all verticeshas("User", "name", "Alice")finds Alice’s User vertexout("owns")follows the “owns” edge to Alice’s accountin_e("Transaction")traverses incoming Transaction edges (money coming in)has("amount", P.gte(100))filters to transactions with amount greater than or equal to 100out_v()moves to the source vertices of those transactions (sending accounts)in_("owns")follows “owns” edges backwards to find the owning usersvalue_map("name")returns a map of properties for each user (in this case, just the name)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()- equalsP.neq()- not equalsP.lt()- less thanP.lte()- less than or equalP.gt()- greater thanP.gte()- greater than or equalP.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:
V()starts at all verticeshas("User", "name", "Bob")filters to Bob’s User vertexvalue_map()returns a dictionary of all properties on the vertexnext()executes the query and returns the first (and only) result
Output example:
userId: U2name: Bobage: 35The 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 verticesE()- start at edgeshas(),has_label()- filter by properties or labelsout(),in_()- traverse edges to adjacent verticesout_e(),in_e()- traverse to adjacent edgesout_v(),in_v()- traverse from edges to verticesvalues()- extract property valuesvalue_map()- extract all properties as a map
Terminal steps:
next()- return the next resultto_list()- return all results as a listiterate()- execute without returning results
Modulation:
as_()- label a step for later referenceselect()- return labeled elementsby()- 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:
- Path traversal: Start at a vertex, follow edges to related vertices (Query 1 and 3).
- Aggregation: Group vertices or edges and compute summary statistics (Query 2).
- 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.