Last active
August 29, 2015 14:02
-
-
Save lfo/f896ce05e3046adfe4e3 to your computer and use it in GitHub Desktop.
Song recommendation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
digraph songGraph { | |
node [shape = circle, border = solid]; | |
Artist [ style = filled, color="#f25a29" ]; | |
Song [ style = filled, color="#30b6af" ]; | |
Person [ style = filled, color="#ad62ce" ]; | |
Artist -> Song [ label = "RECORDED " ]; | |
Person -> Song [ label = "LOVES " ]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
== Song Recommendation | |
According to this simple following graph : | |
image::https://gist.github.com/lfo/f896ce05e3046adfe4e3/raw/f676b878e0cbe6389b2a5b4b7f987d781a7de77b/model.png[] | |
I would like to get recommendation for songs and artists. Indeed, Artist has recorded songs that some persons love. | |
If somebody love the same song than mine, I will more probably love its other loved songs. | |
In order to illustrate, I do the following setup : | |
//setup | |
[source,cypher] | |
---- | |
CREATE (SuzanneVega:Artist{name:'Suzanne Vega'}), | |
(PinkFloyd:Artist{name:'Pink Floyd'}), | |
(TheThe:Artist{name:'The The'}), | |
(Pink:Artist{name:'Pink'}) | |
CREATE SuzanneVega -[:RECORDED]-> (Luka:Song{title:'Luka'}), | |
SuzanneVega -[:RECORDED]-> (TomsDiner:Song{title:'Tom\'s Diner'}), | |
PinkFloyd -[:RECORDED]-> (HighHopes:Song{title:'High Hopes'}), | |
PinkFloyd -[:RECORDED]-> (Mother:Song{title:'Mother'}), | |
PinkFloyd -[:RECORDED]-> (HeyYou:Song{title:'HeyYou'}), | |
TheThe -[:RECORDED]-> (SoulCatcher:Song{title:'Soul Catcher'}), | |
Pink -[:RECORDED]-> (Sober:Song{title:'Sober'}), | |
Pink -[:RECORDED]-> (SoWhat:Song{title:'SoWhat'}) | |
CREATE (Me:Person{login:'Laurent F.'}), | |
(Frederic:Person{login:'Frédéric C.'}), | |
(Benoit:Person{login:'Benoit P.'}), | |
(Fabrice:Person{login:'Fabrice A.'}), | |
(Lilian:Person{login:'Lilian B.'}), | |
(Laurent:Person{login:'Laurent B.'}), | |
(Vincent:Person{login:'Vincent Van S.'}), | |
(Damien:Person{login:'Damien R.'}) | |
CREATE | |
Me-[:LOVES]->Luka, | |
Me-[:LOVES]->TomsDiner, | |
Me-[:LOVES]->HighHopes, | |
Me-[:LOVES]->Mother, | |
Me-[:LOVES]->HeyYou, | |
Me-[:LOVES]->SoulCatcher, | |
Me-[:LOVES]->Sober, | |
Me-[:LOVES]->SoWhat, | |
Frederic-[:LOVES]->HighHopes, | |
Frederic-[:LOVES]->Mother, | |
Frederic-[:LOVES]->HeyYou, | |
Fabrice-[:LOVES]->SoulCatcher, | |
Lilian-[:LOVES]->Sober, | |
Lilian-[:LOVES]->SoWhat, | |
Benoit -[:LOVES]-> SoWhat, | |
Laurent -[:LOVES]->Sober, | |
Laurent -[:LOVES]-> SoulCatcher, | |
Vincent -[:LOVES]->Sober, | |
Vincent -[:LOVES]->Mother | |
---- | |
//graph | |
== What are the most loved song == | |
[source,cypher] | |
---- | |
MATCH ()-[loves:LOVES]->(song:Song) | |
WITH song.title AS title, count(loves) AS counter | |
RETURN title, counter | |
ORDER BY counter DESC , title | |
---- | |
//table | |
=== The same result with Artist name === | |
[source,cypher] | |
---- | |
MATCH ()-[loves:LOVES]->(song:Song)<-[RECORDED]- (artist:Artist) | |
WITH artist.name AS artist, song.title AS title, count(loves) AS counter | |
RETURN title, artist, counter | |
ORDER BY counter DESC , artist | |
---- | |
//table | |
== Get one recommendation for Benoit == | |
Get all the song that is loved by other person, knowing that Benoit love the same song than this other person, ordered by the most loved song. | |
[source,cypher] | |
---- | |
MATCH (benoit:Person)-[:LOVES]-> (song:Song) <-[:LOVES]- (otherPerson:Person)-[:LOVES]->(otherSong:Song)<-[otherLoves:LOVES]-() | |
WHERE benoit.login = 'Benoit P.' | |
WITH otherSong.title AS title, count(distinct otherLoves) as counter | |
RETURN title, counter | |
ORDER BY counter DESC, title | |
LIMIT 3; | |
---- | |
//table | |
In order to understand, the result we can construct our query step by step : | |
=== Step One === | |
Get all LOVES relation from benoit | |
[source,cypher] | |
---- | |
MATCH (benoit:Person)-[loves:LOVES]-> (song:Song) | |
where benoit.login = 'Benoit P.' | |
return loves, song.title; | |
---- | |
//table | |
=== Step Two === | |
Get all LOVES relation from persons that also have the previous LOVES relation. That means, we are looking for all loved song by people who loved also love benoit's loved song. | |
[source,cypher] | |
---- | |
MATCH (benoit:Person)-[:LOVES]->(song:Song)<-[:LOVES]-(otherPerson:Person)-[otherLoves:LOVES]->(otherSong:Song) | |
WHERE benoit.login = 'Benoit P.' | |
RETURN otherLoves; | |
---- | |
//table | |
== Get Recommendation for Damien == | |
[source,cypher] | |
---- | |
MATCH (damien:Person)-[:LOVES]-> (song:Song) <-[:LOVES]- (otherPerson:Person)-[:LOVES]->(otherSong:Song)<-[otherLoves:LOVES]-() | |
WHERE damien.login = 'Damien R.' | |
WITH otherSong.title AS title, count(distinct otherLoves) as counter | |
RETURN title, counter | |
ORDER BY counter DESC, title | |
LIMIT 3; | |
---- | |
//table | |
Damien does not love any song at all for instance, so in order to give him some suggestions, maybe we can use one of the previous query. That means we can use the most loved song query, and use the union operator. | |
[source,cypher] | |
---- | |
MATCH (damien:Person)-[:LOVES]->(song:Song)<-[:LOVES]-(otherPerson:Person)-[:LOVES]->(otherSong:Song)<-[otherLoves:LOVES]-() | |
WHERE damien.login = 'Damien R.' | |
WITH otherSong.title AS title, count(otherLoves) AS counter | |
RETURN title, counter | |
ORDER BY counter DESC , title | |
LIMIT 3 | |
UNION | |
MATCH ()-[loves2:LOVES]->(song2:Song) | |
WITH song2.title AS title, count(loves2) AS counter | |
RETURN title, counter | |
ORDER BY counter DESC , title | |
LIMIT 3; | |
---- | |
//table | |
== Artist Recommendation == | |
TODO | |
Another example is given here : https://github.com/spring-projects/spring-data-neo4j/blob/master/spring-data-neo4j-examples/cineasts/src/main/java/org/neo4j/cineasts/repository/MovieRepository.java | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment