Use cases

Recommendations

A recommendation is a short walk through a graph: from a customer to what they bought, to who else bought it, to what those people bought next. Cypher writes that walk as the pattern it is.

The problem

In a relational schema each hop is a self-join on the orders table, and the query that ranks suggestions for one customer joins it three times. It gets slower with every order and harder to read with every rule you add.

In a graph, purchases are relationships that are followed, not looked up. The three queries below are the usual building blocks: also-bought, similar customers, and suggestions that leave out what the customer already has.

Try it with this dataset

Five customers, seven products in two categories, sixteen purchases. Run this in your GraphBuff checkout (get one in a single command); it downloads shop.cypher, loads it and leaves you in the shell.

$ curl -O https://graphbuff.com/datasets/shop.cypher
$ cargo run --release -p graphbuff-cli -- -i shop.cypher
14 nodes created, 23 relationships created, 21 properties set, 14 labels added

Customers who bought the tent also bought

Query 1

Two hops: from the product to its buyers, then to their other products.

MATCH (:Product {name: 'Tent'})<-[:BOUGHT]-(c:Customer)-[:BOUGHT]->(other:Product)
RETURN other.name AS alsoBought, count(c) AS customers
ORDER BY customers DESC, alsoBought LIMIT 3;
+----------------+-----------+
| alsoBought     | customers |
+----------------+-----------+
| "Camp stove"   | 2         |
| "Head lamp"    | 2         |
| "Sleeping bag" | 2         |
+----------------+-----------+
3 rows

Who shops like Ada?

Query 2

Customers ranked by how many of Ada's products they also bought.

MATCH (me:Customer {name: 'Ada'})-[:BOUGHT]->(p:Product)<-[:BOUGHT]-(peer:Customer)
RETURN peer.name AS peer, count(p) AS shared, collect(p.name) AS products
ORDER BY shared DESC, peer;
+-------+--------+--------------------------+
| peer  | shared | products                 |
+-------+--------+--------------------------+
| "Ben" | 2      | ["Tent", "Sleeping bag"] |
| "Dan" | 2      | ["Tent", "Head lamp"]    |
| "Eve" | 1      | ["Sleeping bag"]         |
+-------+--------+--------------------------+
3 rows

What to suggest to Ada

Query 3

Products her peers bought and she did not, ranked by how many peers bought them.

MATCH (me:Customer {name: 'Ada'})-[:BOUGHT]->(:Product)<-[:BOUGHT]-(peer:Customer)
      -[:BOUGHT]->(rec:Product)-[:IN]->(cat:Category)
WHERE NOT (me)-[:BOUGHT]->(rec)
RETURN rec.name AS recommend, cat.name AS category, count(DISTINCT peer) AS peers
ORDER BY peers DESC, recommend;
+------------------+-----------+-------+
| recommend        | category  | peers |
+------------------+-----------+-------+
| "Camp stove"     | "Camping" | 2     |
| "Hiking boots"   | "Hiking"  | 2     |
| "Trekking poles" | "Hiking"  | 1     |
+------------------+-----------+-------+
3 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