如何优化下面的Cypher查询以实现分页


MATCH (user:Users {id: 1})<-[ct:COMMENT]<-(co:Comment)<-[ct_by:COMMENTED_BY]-(c_user:Users)
OPTIONAL MATCH (co)<-[rt:REPLY]<-(r_co:Comment)<-[r_co_by:REPLIED_BY]-(r_co_user:Users)
OPTIONAL MATCH (co)<-[co_lk:LIKES]-(co_lk_user:Users)
OPTIONAL MATCH (r_co)<-[r_co_lk:LIKES]-(r_co_lk_user:Users)
OPTIONAL MATCH (user)<-[rv:REVIEW]-(rv_user:Users)
RETURN co,c_user,r_co,r_co_user,rv,rv_user,COUNT(co_lk_user) AS co_likes,COUNT(r_co_lk) AS r_co_likes ORDER BY ct_by.created_at DESC, r_co_by.created_at

上面的Cypher编写了用于获取所有评论,回复和喜欢的评论以及类似于用户feed的用户的评论。上述查询的输出是混乱的,并在应用程序层和分页上处理。关于如何优化上述Cypher以及查询本身的分页的任何建议真的很有帮助。

此查询的最大问题是您不使用聚合来收集独立的数据段在您的数据中,很可能也会丢弃您的计数。

例如,在您的返回中,您正在评论和评论之间生成跨产品。实际上,我真的建议您在单独的查询中收到评论,否则(前提是您收集评论),您将在每个记录中都会获得相同的评论,这似乎很浪费。

这是一个替代查询,应该对您更有效(目前,在查询中保留收集的评论):

MATCH (user:Users {id: 1})
WITH user, [(user)<-[rv:REVIEW]-(rv_user:Users) | rv {.*, reviewer:rv_user}] as reviews
OPTIONAL MATCH (user)<-[:COMMENT]-(co:Comment)<-[ct_by:COMMENTED_BY]-(c_user:Users)
WITH reviews, co, ct_by, c_user
OPTIONAL MATCH (co)<-[:REPLY]-(r_co:Comment)<-[r_co_by:REPLIED_BY]-(r_co_user:Users)
WITH reviews, co, ct_by, c_user, r_co, r_co_by, r_co_user
ORDER BY ct_by.created_at DESC, r_co_by.created_at 
SKIP $skip LIMIT $limit
RETURN reviews, co, ct_by, c_user, r_co, r_co_user, size((co)<-[:LIKES]-()) AS co_likes, size((r_co)<-[:LIKES]-()) AS r_co_likes

我们将模式理解和映射投影的组合与第一个条款与审稿人一起收集评论。

我们完成与ct_byr_co_by匹配后,我们可以使用跳过和限制应用分页,尽管您需要提供这些参数,并调用下一页的查询,然后跳过限制的倍数(您可以更改(您可以更改)相应地,如果这使它变得更容易)。

我们在模式上使用size()函数来获取出现的数量,这更容易获得喜欢的人,尤其是从节点本身的关系程度数据中获取此产品,而不是必须展开(前提是全部:喜欢关系来自:用户)。

例如,我们可以从这里进行更多改进,例如,收集每个评论的答复数据:

MATCH (user:Users {id: 1})
WITH user, [(user)<-[rv:REVIEW]-(rv_user:Users) | rv {.*, reviewer:rv_user}] as reviews
OPTIONAL MATCH (user)<-[:COMMENT]-(co:Comment)<-[ct_by:COMMENTED_BY]-(c_user:Users)
WITH reviews, co, ct_by, c_user
OPTIONAL MATCH (co)<-[:REPLY]-(r_co:Comment)<-[r_co_by:REPLIED_BY]-(r_co_user:Users)
WITH reviews, co, ct_by, c_user, r_co, r_co_by, r_co_user
ORDER BY ct_by.created_at DESC, r_co_by.created_at 
SKIP $skip LIMIT $limit
WITH reviews, co, ct_by, c_user, r_co, r_co_user, size((co)<-[:LIKES]-()) AS co_likes, size((r_co)<-[:LIKES]-()) AS r_co_likes
RETURN reviews, co, ct_by, c_user, co_likes, collect(r_co {.*, replier:r_co_user, likes:r_co_likes}) as replies

最新更新