Over a million developers have joined DZone.

Designing Recommendation Queries in Neo4j

DZone 's Guide to

Designing Recommendation Queries in Neo4j

· Java Zone ·
Free Resource

Recommendation is a hot topic these days. Using a graph database it is easy to create great recommendation queries.

Here are a few steps for designing excellent recommendation queries for your applications.

Let's start by outlining what recommendation means within this context.

A classic recommendation example is Amazon's "People who viewed X also viewed Y" or "People who bought X also bought Y". In graph language this means that X and Y are nodes in which there is a strong correlation between them. By strong correlation I mean some kind of relationships of value.

In the image above, you'll see P1, P2, and P3, which represent people. Also, you'll see X, which is our item of interest, and you'll see Y1, Y2, Y3, Y4, and Y5.

This is a basic recommendation data model, and it recurs quite frequently. The very same model can be applied to movie recommendations with keywords and movies. It can be applied to a social network for recommending friends with similar interests. It can be used to recommend products to customers of an eCommerce website.

So what's going on here? How do you use Neo4j to recommend Y to people who view X?

In the image below I've highlighted in red the primitives that we are interested in. We first want to find all the people who viewed X. Next we want to find all the Ys that those people viewed. Last we only want to match Ys that people viewed who also viewed X. While Y2-Y4 are technically relevant, no one else viewed those items who also viewed X.

Now let's take a look at an example in Neo4j. The following Cypher script sets up our dataset:

 MERGE (x:Item { id: "x" })
 MERGE (y1:Item { id: "y1" })
 MERGE (y2:Item { id: "y2" })
 MERGE (y3:Item { id: "y3" })
 MERGE (y4:Item { id: "y4" })
 MERGE (y5:Item { id: "y5" })
 MERGE (p1:Person { id: "p1" })
 MERGE (p2:Person { id: "p2" })
 MERGE (p3:Person { id: "p3" })
 MERGE (p1)-[:VIEWED]->(y1)
 MERGE (p1)-[:VIEWED]->(y2)
 MERGE (p1)-[:VIEWED]->(y3)
 MERGE (p1)-[:VIEWED]->(y4)
 MERGE (p1)-[:VIEWED]->(y5)
 MERGE (p1)-[:VIEWED]->(x)
 MERGE (p2)-[:VIEWED]->(y1)
 MERGE (p2)-[:VIEWED]->(x)
 MERGE (p3)-[:VIEWED]->(y5)
 MERGE (p3)-[:VIEWED]->(x)

Which results in the following result in the Neo4j 2.0 browser:

Given the result of the setup query, we see the above graph, which matches our design in the earlier images. The difference here is that I've assigned a label to items and people, where items are red and people are purple. This makes it easier for us to match the desired recommendation pattern in the graph.

The scenario is that someone is viewing X's item page on Amazon.com. We have a widget on that page with the requirement to show "People who viewed X also viewed Y". Which is a list of Y sorted in descending order of most views to Y who also viewed X.

That Cypher query looks like this:

 MATCH (x:Item { id: "x" })<-[:VIEWED]-(p:Person),
 WITH y.id as Y, count(p) as count
 WHERE count > 1
 RETURN Y, count

Which results in the following:

So the answer to the question, "People who viewed X also viewed Y", results in Y1 and Y5.

Feel free to scale this example up to concrete examples in your own domain. Model it out using a similar process that I did above and create your sample dataset to do your recommendations.

  • Start with your question
  • Design a data model that answers that question
  • Design your recommendation queries to answer the question on your data model
  • Scale up your data set to a production scenario

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}