Use cases

Fraud and network analysis

Fraud shows up as shape: money that returns to where it started, accounts that share a phone, a cluster that only trades with itself. Those are graph algorithms and path patterns, and GraphBuff has both built in.

The problem

Row-by-row rules see one transfer at a time. A ring of three accounts passing the same money around looks normal in every single row; it only shows when the transfers are followed as a path.

The algorithm procedures (connected components, PageRank, triangle counts, breadth-first search) run on the CPU, or on the GPU with --gpu. This dataset is tiny, so it runs on the CPU: kernels move to the GPU from 262,144 relationships up.

Try it with this dataset

Eight accounts, seven transfers, three devices. Run this in your GraphBuff checkout (get one in a single command); it downloads transfers.cypher, loads it and leaves you in the shell.

$ curl -O https://graphbuff.com/datasets/transfers.cypher
$ cargo run --release -p graphbuff-cli -- -i transfers.cypher
11 nodes created, 13 relationships created, 26 properties set, 11 labels added

Which accounts form a cluster?

Query 1

Weakly connected components over the transfers: each component with more than one account is a group that moved money among themselves.

CALL algo.wcc({relationshipTypes: 'SENT'}) YIELD node, componentId
WITH componentId, collect(node.id) AS accounts
WHERE size(accounts) > 1
RETURN componentId, accounts ORDER BY size(accounts) DESC, componentId;
+-------------+--------------------------------------+
| componentId | accounts                             |
+-------------+--------------------------------------+
| 0           | ["A-101", "A-102", "A-103", "A-104"] |
| 4           | ["A-105", "A-106"]                   |
| 6           | ["A-107", "A-108"]                   |
+-------------+--------------------------------------+
3 rows

Where does money go round in a circle?

Query 2

Paths of two to four transfers that end where they began, each ring listed once.

MATCH p = (a:Account)-[:SENT*2..4]->(a)
WITH p, [n IN nodes(p) | n.id] AS ring
WHERE ring[0] = apoc.coll.min(ring)
RETURN ring, reduce(total = 0, r IN relationships(p) | total + r.amount) AS moved
ORDER BY moved DESC;
+--------------------------------------+-------+
| ring                                 | moved |
+--------------------------------------+-------+
| ["A-101", "A-102", "A-103", "A-101"] | 2640  |
| ["A-105", "A-106", "A-105"]          | 325   |
+--------------------------------------+-------+
2 rows

Which accounts share a device?

Query 3

Different holders logging in from one phone is the second signal for the ring above.

MATCH (d:Device)<-[:USES]-(a:Account)
WITH d, collect(a.holder) AS holders
WHERE size(holders) > 1
RETURN d.id AS device, holders ORDER BY size(holders) DESC;
+-------------+------------------------+
| device      | holders                |
+-------------+------------------------+
| "phone-7f3" | ["Iris", "Jon", "Kai"] |
| "phone-b41" | ["Milo", "Nora"]       |
+-------------+------------------------+
2 rows

Not running GraphBuff yet?

$ docker run --rm -p 127.0.0.1:7475:7475 -p 127.0.0.1:7687:7687 ghcr.io/janvencl/graphbuff --demo movies

Needs Docker. Full walkthrough