获取属于一组标签的所有电影
Getting all movies belonging to a set of tags
所以我有一个 Neo4J 电影数据库及其类型。我想找到一组属于所有类型的所有电影。
EG:
Matrix - Sci-fi, Thriller, Action
Harry Potter - Drama, Fiction, Thriller
Pulp Fiction - Drama, Thriller
现在,我想要的是属于Drama的电影,还有Thriller。
这意味着 Harry 和 Pulp,但不是 Matrix,尽管它也属于 Thriller。
对查询有什么想法吗?
您可以 MATCH
您的 Movie
节点并过滤两个 Genre
节点的关系:
MATCH (m:Movie)
WHERE (m)-[:GENRE]->(:Genre {genre_name: 'Drama'})
AND (m)-[:GENRE]->(:Genre {genre_name: 'Thriller'})
RETURN m
考虑以下数据集:
Create (g1:Genre {name: 'Sci-fi' } )
Create (g2:Genre {name: 'Thriller' } )
Create (g3:Genre {name: 'Action' } )
Create (g4:Genre {name: 'Drama' } )
Create (g5:Genre {name: 'Fiction' } )
Create (m1:Movie {name: 'Matrix' } )
Create (m1)-[:IS_GENRE]->(g1)
Create (m1)-[:IS_GENRE]->(g2)
Create (m1)-[:IS_GENRE]->(g3)
Create (m2:Movie {name: 'Harry Potter' } )
Create (m2)-[:IS_GENRE]->(g4)
Create (m2)-[:IS_GENRE]->(g5)
Create (m2)-[:IS_GENRE]->(g2)
Create (m3:Movie {name: 'Pulp Fiction' } )
Create (m3)-[:IS_GENRE]->(g4)
Create (m3)-[:IS_GENRE]->(g2)
如果您使用以下查询,您只能匹配特定列表中的流派,但只有 return 结果,其中每部电影的流派数量与您的列表大小相同。
with ['Thriller','Drama'] as genre_list
match (m:Movie)-[r:IS_GENRE]->(g:Genre)
using index g:Genre(name)
where g.name in genre_list
with genre_list,m.name as movie, collect(g.name) as genres
where size(genres) = size(genre_list)
return movie, genres
如果您只有两种类型可以匹配,我认为这很有趣...
match p=allShortestPaths((g1:Genre {name: 'Thriller'} )-[:IS_GENRE*..2]-(g2:Genre {name: 'Drama'} ))
using index g1:Genre(name)
using index g2:Genre(name)
return (nodes(p)[1]).name as movie, [(nodes(p)[0]).name, (nodes(p)[2]).name] as genres
您不需要在每个方向(contains
和 genres
)建立关系,正如您在评论中提到的那样。只有一个方向就足够了,因为您可以轻松地在任一方向上遍历关系。在这个答案中,我将只使用 genre
关系。
我假设您首先在 Genre
节点的 name
属性 上创建索引。
CREATE INDEX ON :Genre(name);
该索引将允许下面的实际查询快速获取所需的 Genre
节点,而无需遍历每个此类节点。
MATCH (g1:Genre { name: 'Drama' })<-[:genre]-(m:Movie)-[:genre]->(g2:Genre { name: 'Thriller' })
USING INDEX g1:Genre(name)
USING INDEX g2:Genre(name)
RETURN m;
这个简单而高效的查询强制(通过 USING INDEX
)Cypher 规划器对两个 Genre
节点使用上述索引(因为规划器目前只为其中一个节点自动执行此操作)。
所以我有一个 Neo4J 电影数据库及其类型。我想找到一组属于所有类型的所有电影。
EG:
Matrix - Sci-fi, Thriller, Action
Harry Potter - Drama, Fiction, Thriller
Pulp Fiction - Drama, Thriller
现在,我想要的是属于Drama的电影,还有Thriller。 这意味着 Harry 和 Pulp,但不是 Matrix,尽管它也属于 Thriller。
对查询有什么想法吗?
您可以 MATCH
您的 Movie
节点并过滤两个 Genre
节点的关系:
MATCH (m:Movie)
WHERE (m)-[:GENRE]->(:Genre {genre_name: 'Drama'})
AND (m)-[:GENRE]->(:Genre {genre_name: 'Thriller'})
RETURN m
考虑以下数据集:
Create (g1:Genre {name: 'Sci-fi' } )
Create (g2:Genre {name: 'Thriller' } )
Create (g3:Genre {name: 'Action' } )
Create (g4:Genre {name: 'Drama' } )
Create (g5:Genre {name: 'Fiction' } )
Create (m1:Movie {name: 'Matrix' } )
Create (m1)-[:IS_GENRE]->(g1)
Create (m1)-[:IS_GENRE]->(g2)
Create (m1)-[:IS_GENRE]->(g3)
Create (m2:Movie {name: 'Harry Potter' } )
Create (m2)-[:IS_GENRE]->(g4)
Create (m2)-[:IS_GENRE]->(g5)
Create (m2)-[:IS_GENRE]->(g2)
Create (m3:Movie {name: 'Pulp Fiction' } )
Create (m3)-[:IS_GENRE]->(g4)
Create (m3)-[:IS_GENRE]->(g2)
如果您使用以下查询,您只能匹配特定列表中的流派,但只有 return 结果,其中每部电影的流派数量与您的列表大小相同。
with ['Thriller','Drama'] as genre_list
match (m:Movie)-[r:IS_GENRE]->(g:Genre)
using index g:Genre(name)
where g.name in genre_list
with genre_list,m.name as movie, collect(g.name) as genres
where size(genres) = size(genre_list)
return movie, genres
如果您只有两种类型可以匹配,我认为这很有趣...
match p=allShortestPaths((g1:Genre {name: 'Thriller'} )-[:IS_GENRE*..2]-(g2:Genre {name: 'Drama'} ))
using index g1:Genre(name)
using index g2:Genre(name)
return (nodes(p)[1]).name as movie, [(nodes(p)[0]).name, (nodes(p)[2]).name] as genres
您不需要在每个方向(
contains
和genres
)建立关系,正如您在评论中提到的那样。只有一个方向就足够了,因为您可以轻松地在任一方向上遍历关系。在这个答案中,我将只使用genre
关系。我假设您首先在
Genre
节点的name
属性 上创建索引。CREATE INDEX ON :Genre(name);
该索引将允许下面的实际查询快速获取所需的
Genre
节点,而无需遍历每个此类节点。MATCH (g1:Genre { name: 'Drama' })<-[:genre]-(m:Movie)-[:genre]->(g2:Genre { name: 'Thriller' }) USING INDEX g1:Genre(name) USING INDEX g2:Genre(name) RETURN m;
这个简单而高效的查询强制(通过
USING INDEX
)Cypher 规划器对两个Genre
节点使用上述索引(因为规划器目前只为其中一个节点自动执行此操作)。