Sachin Vairagi
Sachin Vairagi

Reputation: 5344

Neo4j - User's search history based recommendation

I have Following labels :-

My app user has search bar where they can type and search anything , I am storing users searched contents for a limited period of time for future recommendations.What will be the query for Recommendation based on Users search history? Should I need to create relationship of search history? After gone through some tutorial for recommendations , I am little bit able to write following query -

MATCH (m:Movie)<-[:LIKE]-(p:Person {personId : 1})
OPTIONAL MATCH (t:Tag)
WITH collect(distinct t.tagName) as c1

OPTIONAL MATCH (g:Genre) 
WITH collect(distinct g.name) + c1 as c2

OPTIONAL MATCH (l:Language) 
WITH collect(distinct l.languageName) + c2 as c3
RETURN c3

It is not a complete query but a rough idea and am not sure is it correct way? Can anybody help me to achieve it? Thanks much!!

Upvotes: 0

Views: 275

Answers (1)

Christophe Willemsen
Christophe Willemsen

Reputation: 20185

Well with your current model, I assume you can do recommendations like :

Find people liking the same movies as you, what other movies do they like that you didn't watched yet

MATCH (p:Person {personId: 1})-[:LIKE]->(movie)<-[:LIKE]-(other)
WITH distinct other, p
MATCH (other)-[:LIKE]->(reco)
WHERE NOT (p)-[:LIKE]->(reco)
RETURN reco, count(*) as score
ORDER BY score DESC

You can apply the same kind of queries for finding movies having the same genres, etc.. and combine the results afterwards.

There is a good blog post with lot of example queries for recommendations with Cypher : http://www.markhneedham.com/blog/2015/03/27/neo4j-generating-real-time-recommendations-with-cypher/

For recommendations based on search, an easy solution is to split the search string into elements, for example :

WITH split("action movie with arnold in 1997", " ") AS elements
MATCH (m:Movie)<-[r]-(object)
WHERE object.value IN elements
RETURN m, count(*) as score

This would assume that all nodes representing a property of a movie would have a common value property, so :Tag(value), :Year(value), :Title(value)

This is kind of basic, in common recommender systems based on search history, you would model the history like a timeline :

(user)-[:LAST_SEARCH]->(s)-[:PREV_SEARCH]->(s)..
(s)-[:HAS_KEYWORD]->(keyword)

enter image description here

Then you will compute the similarity between search histories continuously as a background job. A common algorithm is cosine similarity or likelihood function

You then can find potential similar searches and returned movies based on the similarity with the current user history and other user histories.

Lastly of course, you can combine all of the recommendation logic and compute a final score.

And based on your comment :

Users search keyword could be anything like movie title , actor name , tag etc.So for example if it is a tag name then I want to present those movies having the same tag

This is more pattern matching and doesn't really fall in the topic of recommendations.

Upvotes: 3

Related Questions