0

I have 3 nodes:

  • Users (id, age).
  • Ratings (isbn, id, rating (this has a value of 0 to 10)).
  • Books (isbn, title, ...)

And the relationships:

Users - [GIVE_RATINGS]-Ratings -[BELONGS_TO]- Books

I need to create a recommendation where the input will be one or more books the reader liked, and the output will be books that users who rated positively also rated books the reader has already read.

I tried to create such a query, but it doesn't work.

MATCH (u:Users{id:'11676'})-[:GIVE_RATING]->(book)<-[:GIVE_RATING]-(person), (person)-[:GIVE_RATING]->(book2)<-[:GIVE_RATING]-(r:Ratings{rating:'9'}) 
WHERE NOT EXIST (book2)-[:GIVE_RATING]->(u) 
RETURN book2.isbn,person.id
David Makogon
  • 69,407
  • 21
  • 141
  • 189
  • 1
    What do you mean "it doesn't work"? Is there a syntax error, does it not return the results you want, ...? – Aaron Meese Jan 21 '23 at 23:41
  • It return syntax error: Invalid input ':': expected whitespace, a variable, RelationshipsPattern, an expression or ']' (line 1, column 176 (offset: 175)) "MATCH (u:Users{id:'11676'})-[:GIVE_RATING]->(book)<-[:GIVE_RATING]-(person), (person)-[:GIVE_RATING]->(book2)<-[:GIVE_RATING]-(r:Ratings{rating:'9'}) WHERE NOT EXIST (book2)-[:GIVE_RATING]->(u) RETURN book2.isbn,person.id" ... points to (r:Ratings{rating:'9'} – Stokinger Jan 22 '23 at 08:51
  • Does this answer your question? [Searching not exists in Neo4j via Cypher](https://stackoverflow.com/questions/36008315/searching-not-exists-in-neo4j-via-cypher) – knittl Jan 22 '23 at 11:21
  • You want `WHERE NOT EXISTS((book2)-[:GIVE_RATING]->(u))` (note the "S" and parens) – knittl Jan 22 '23 at 11:21

1 Answers1

0

you probably want to store your ratings as integers or floats, not strings, better to use [not] exists { pattern } in newer versions

A common recommendation statement would look like this:

MATCH (u:Users{id:$user})-[:GIVE_RATING]->(rating)
      <-[:GIVE_RATING]-(person)-[:GIVE_RATING]->(rating2)
      <-[:GIVE_RATING]-(rating3) 
WHERE abs(rating2.rating - rating.rating) <= 2 // similar ratings
AND rating3.rating >= 9
AND NOT EXIST { (rating3)<-[:GIVE_RATING]-(u) } 
WITH rating3, count(*) as freq
RETURN rating3.isbn,person.id
ORDER BY freq DESC LIMIT 5

You could also represent your rating information on the relationship between user and book, no need for the extra Node.

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80