如何使用多个可选匹配来优化Cypher-Query

时间:2017-05-16 10:26:40

标签: neo4j cypher

我有以下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

您能不能给我一个如何优化此查询的提示?

3 个答案:

答案 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