azngunit81
azngunit81

Reputation: 1604

Graph DB get the next best recommended node in Neo4j cypher

I have a graph using NEO4j and currently trying to build a simple recommendation system that is better than text based search.

Nodes are created such as: Album, People, Type, Chart

Relationship are created such as:

People - [:role] -> Album where roles are: Artist, Producer, Songwriter

Album-[:is_a_type_of]->Type (type is basically Pop, Rock, Disco...)

People -[:POPULAR_ON]->Chart (Chart is which Billboard they might have been)

People -[:SIMILAR_TO]->People (Predetermined similarity connection)

I have written the following cypher:

    MATCH (a:Album { id: { id } })-[:is_a_type_of]->(t)<-[:is_a_type_of]-(recommend)    
    WITH recommend, t, a
    MATCH (recommend)<-[:ARTIST_OF]-(p)
    OPTIONAL MATCH (p)-[:POPULAR_ON]->()
    RETURN recommend, count(DISTINCT t) AS type
    ORDER BY type DESC
    LIMIT 25;

It works however, it easily repeats itself if it has only one type of music connected to it, therefore has the same neighbors.

Is there a suggested way to say:

Upvotes: 5

Views: 428

Answers (1)

Somnath Muluk
Somnath Muluk

Reputation: 57816

You can use 4 configurations and order albums according to higher value in this order. Keep configuration between 0 to 1 (ex. 0.6)

a. People Popular on Chart and People are similar
b. People Popular on Chart and People are Not similar
c. People Not Popular on Chart and People are similar
d. People Not Popular on Chart and People are Not similar

Calculate and sum these 4 values with each album. Higher the value, higher recommended Album.

I have temporarily made config as a = 1, b =0.8, c=0.6, d = 0.4. And assumed some relationship present which suggests some People Likes Album. If you are making logic based on Chart only then use a & b only.

MATCH (me:People)
where id(me) = 123
MATCH (a:Album { id: 456 })-[:is_a_type_of]->(t:Type)<-[:is_a_type_of]-(recommend)    
OPTIONAL MATCH (recommend)<-[:ARTIST_OF]-(a:People)-[:POPULAR_ON]->(:Chart)
WHERE exists((me)-[:SIMILAR_TO]->(a))
OPTIONAL MATCH (recommend)<-[:ARTIST_OF]-(b:People)-[:POPULAR_ON]->(:Chart)
WHERE NOT exists((me)-[:SIMILAR_TO]->(b))
OPTIONAL MATCH (recommend)<-[:LIKES]-(c:People)
WHERE exists((me)-[:SIMILAR_TO]->(a))
OPTIONAL MATCH (recommend)<-[:LIKES]-(d:People)
WHERE NOT exists((me)-[:SIMILAR_TO]->(a))
RETURN recommend, (count(a)*1 + count(b)*0.8 + count(c)* 0.6+count(d)*0.4) as rec_order
ORDER BY rec_order DESC
LIMIT 10;

Upvotes: 2

Related Questions