neo4j 这个密码查询有更简单的版本吗?

jjjwad0x  于 2023-02-22  发布在  其他
关注(0)|答案(1)|浏览(146)

我构建了一个查询,以查找那些相互关注并阅读过同类书籍的人,如下所示:

MATCH (u1:User)-[:READ]->(b1:Book)
WITH collect(DISTINCT b1.genre) AS genres,u1 AS user1
MATCH (u2:User)-[:READ]->(b2:Book)
WHERE (user1)<-[:FOLLOWS]->(u2) AND b2.genre IN genres
RETURN DISTINCT user1.username AS user1,u2.username AS user2

我们收集其中一个用户的所有图书类型,如果另一个用户阅读的图书也在该类型列表中(并且他们彼此跟随),那么我们就返回这些用户,这似乎是可行的:我们得到了一个不同的成对个体的列表。不过,我想知道,是否有更快的方法来做到这一点?我的解决方案似乎有些笨拙,但我发现,试图指定他们读过同一类型的书,而不取回所有成对的书和复制个体,这是令人惊讶的挑剔。例如,我首先写了以下内容:

MATCH (b1:Book)<-[:READ]-(u1:User)-[:FOLLOWS]-(u2:User)-[:READ]->(b2:Book)
WHERE b1.genre = b2.genre
RETURN DISTINCT u1.username AS user1, u2.username AS user2

这看起来更简单,但实际上它返回了所有阅读过的同一类型书籍的重复名称,我的解决方案是最简单的,还是有更简单的?

sqyvllje

sqyvllje1#

这是重写查询的一种方法

MATCH (n1:User)-[:FOLLOWS]-(n2:User)
MATCH (n1)-[:READ]->(book), (n2)-[:READ]->(book2)
WHERE book.genre = book2.genre
RETURN n1.username, n2.username, count(*)

这里是另一个收集流派为每个用户

MATCH (n1:User)-[:FOLLOWS]-(n2:User)
WITH n1, n2, 
[(n1)-[:READ]->(book) | book.genre] AS g1,
[(n2)-[:READ]->(book) | book.genre] AS g2
WHERE ANY(x IN g1 WHERE x IN g2)
RETURN n1, n2, count(*)

请注意,有时候较长的查询并不是特别好,因为检索数据的方式需要对您自己有意义。
然而,您的模型清楚地表明,您将受益于一点图重构,将流派提取到它自己的节点中,例如

MATCH (n:Book)
MERGE (g:Genre {name: n.genre})
MERGE (n)-[:HAS_GENRE]->(g)

这将是利用图模型的新查询

PROFILE
MATCH (n1:User)-[:FOLLOWS]-(n2:User)
WHERE (n1)-[:READ]->()-[:HAS_GENRE]->()<-[:HAS_GENRE]-()<-[:READ]-(n2)
RETURN n1.username, n2.username, count(*)

相关问题