I use neo4j 5. So it's cypher query language.
goal: Find books with genres among which there is at least one preferred genre and no genre that is avoided.
Data
Blue node - UserDetails
Red node - UserPreferences
Purple node - Genre
Yellow node - Book
Here, user User has preferences
Preferences node related to genres with AVOIDED
relation which means that user don't want to see books with related genre and PREFERRED
which means that user want to see books with at leas one related genre.
Cypher Script to populate the database:
CREATE(:Book {ageLimit: 16, publishedAt: 1999, author: 'Test Author 1', isbn: '0000000000001',
storeUrl: 'https://www.test-image.com/some-uri/book1',
imageUrl: 'https://www.test-image.com/some-uri/book1.jpg',
description: 'Test book description 1.', id: '20c84cdd-50f0-45cf-8269-12daa6a4984b',
title: 'Test Title 1', lang: 'en'})
CREATE (:Book {ageLimit: 18, publishedAt: 2001, author: 'Test Author 2', isbn: '0000000000002',
storeUrl: 'https://www.test-image.com/some-uri/book2',
imageUrl: 'https://www.test-image.com/some-uri/book2.jpg',
description: 'Test book description 2.', id: '75a01e8f-8ab2-4506-a38f-3eef63f3b3cc',
title: 'Test Title 2', lang: 'en'})
CREATE (:Book {ageLimit: 12, publishedAt: 2010, author: 'Test Author 3', isbn: '0000000000003',
storeUrl: 'https://www.test-image.com/some-uri/book3',
imageUrl: 'https://www.test-image.com/some-uri/book3.jpg',
description: 'Test book description 3.', id: '6e15a4e8-12fb-4cf8-8143-c05937fc2f15',
title: 'Test Title 3', lang: 'en'})
CREATE (:Genre {name: 'classical', id: '4a85865a-e903-41f3-a6fa-6d912eaac620'})
CREATE (:Genre {name: 'fantastic', id: 'dca5f095-6296-4c17-85fa-c6c544eea429'})
CREATE (:Genre {name: 'action', id: 'feec627b-7e0f-45f8-81c4-f83b085e7e0c'})
CREATE (:UserDetails {lastName: 'Dow', firstName: 'John', gender: 'MALE', dateOfBirth: '1990-01-01',
id: '075cb495-49b5-42fe-9fec-cef3eb95a49e', userName: 'default_user',
email: 'default_user@email.com'})
CREATE (:UserPreferences {userId: '075cb495-49b5-42fe-9fec-cef3eb95a49e'})
How should i change my query to successfully filtering both of parameters (preferred genres and avoided genres)?
I already tried to complete it by query below, but it ignored avoided genres.
Query:
MATCH (u:UserDetails)
WHERE u.id = $userId
(u)-[:HAS_PREFERENCES]->(up:UserPreferences{userId: u.id})
WITH up
OPTIONAL MATCH (up)-[pref:PREFERRED]->(pg:Genre)
OPTIONAL MATCH (up)-[avoid:AVOIDED]->(ag:Genre)
WITH up, collect(DISTINCT pg) AS pg, collect(DISTINCT ag) AS ag
MATCH (b:Book)-[:BELONGS_TO]->(g:Genre)
WHERE b.lang = 'en'
AND (size(ag) = 0 OR NOT any(genre IN ag WHERE genre = g)) //logic which i expected from this line doesn't work
AND(size(pg) = 0 OR any(genre IN pg WHERE genre = g))
WITH DISTINCT b
LIMIT 5
MATCH (b)-[r:BELONGS_TO]->(g:Genre)
RETURN b, collect(DISTINCT g), collect(r)