我有以下cypher查询,其中包含多个可选匹配项,这些匹配项不能在我的机器上运行(笛卡尔积):
match (document:Document)-[*..2]-(relateddocument:Document)
optional match (document)-[:HAS_CATEGORY]->(c:Category)<-[:HAS_CATEGORY]-(relateddocument)
optional match (document)-[:HAS_KEYWORD]->(k:Keyword)<-[:HAS_KEYWORD]-(relateddocument)
optional match (document)-[:HAS_AUTHOR]->(a:Author)<-[:HAS_AUTHOR]-(relateddocument)
with document, relateddocument, collect(c)+collect(k)+collect(a) as similarity
where id(document) = 85182 return relateddocument, similarity order by similarity desc limit 5
您能不能给我一个如何优化此查询的提示?
答案 0 :(得分:2)
正如其他答案所示,您需要将WHERE
子句尽可能接近相应的MATCH
,以最大限度地减少MATCH
生成的行数。
此外,您可以使用OPTIONAL MATCH
将每个COLLECT
的N行转换为1行,从而消除由所有背对背MATCH
子句引起的笛卡尔积。 (最后WITH
将在RETURN
之前,因此可以&#34;合并&#34;到RETURN
。)
此外,您的ORDER BY similarity DESC
子句没有任何意义(并且可能会导致错误),因为similarity
是一个集合。您可能打算在那里使用SIZE(similarity)
而不是similarity
。
这应该更快:
MATCH (document:Document)-[:HAS_CATEGORY|:HAS_KEYWORD|:HAS_AUTHOR*..2]-(relateddocument:Document)
WHERE ID(document) = 85182
OPTIONAL MATCH (document)-[:HAS_CATEGORY]->(c:Category)<-[:HAS_CATEGORY]-(relateddocument)
WITH document, relateddocument, COLLECT(c) AS cs
OPTIONAL MATCH (document)-[:HAS_KEYWORD]->(k:Keyword)<-[:HAS_KEYWORD]-(relateddocument)
WITH document, relateddocument, cs, COLLECT(k) AS ks
OPTIONAL MATCH (document)-[:HAS_AUTHOR]->(a:Author)<-[:HAS_AUTHOR]-(relateddocument)
RETURN relateddocument, cs+ks+collect(a) as similarity
ORDER BY SIZE(similarity) DESC
LIMIT 5;
请注意,如果您的文档与其他类型有很多关系,则第一个MATCH
也会使用[:HAS_CATEGORY|:HAS_KEYWORD|:HAS_AUTHOR*..2]
来过滤关系类型。这可以进一步减少第一个MATCH
生成的行数,这将减少整个查询所做的工作量。
答案 1 :(得分:0)
立即改进它的一种方法是在MATCH语句下直接移动WHERE id(document)= 85182。如果您查询查询,那么这应该会产生重大影响。
此致 汤姆
答案 2 :(得分:0)
主要问题是match (document:Document)-[*..2]-(relateddocument:Document)
是所有文档与所有文档之间2个链接之间的笛卡尔积,而匹配和id过滤器之间的WITH告诉Cypher不要应用过滤器直到它完成全部工作。通过将WHERE id(...)移动到WITH之前,Cypher将知道将(文档:Document)限制为id 85182是安全的,从而避免了基本上所有文档与所有文档的n ^ 2匹配。 / p>
MATCH (document:Document)-[*..2]-(relateddocument:Document)
WHERE id(document) = 85182
WITH document, relateddocument
OPTIONAL MATCH (document)-[:HAS_CATEGORY]->(c:Category)<-[:HAS_CATEGORY]-(relateddocument)
OPTIONAL MATCH (document)-[:HAS_KEYWORD]->(k:Keyword)<-[:HAS_KEYWORD]-(relateddocument)
OPTIONAL MATCH (document)-[:HAS_AUTHOR]->(a:Author)<-[:HAS_AUTHOR]-(relateddocument)
WITH relateddocument, collect(c)+collect(k)+collect(a) as similarity
RETURN relateddocument, similarity
order by similarity desc
limit 5