---
title: "Review queries"
description: "Learn four essential Gremlin query patterns in Java for analyzing transaction data with Aerospike Graph."
---

# Review queries

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

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):

```java
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

```plaintext
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:

```java
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

```plaintext
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:

```java
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

```plaintext
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:

```java
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

```plaintext
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

::: undefined
-   I understand how to find transactions for a specific user.
-   I understand how to aggregate transaction amounts.
-   I understand how to filter transactions by criteria.
-   I understand how to retrieve vertex properties.
:::

[Previous  
Understand the data model](https://aerospike.com/docs/graph/graph-and-java-basics/step/2/part/0/understand-data-model) [Next  
Modify the graph](https://aerospike.com/docs/graph/graph-and-java-basics/step/3/part/0/modify-graph)