优化Cypher查询

时间:2017-03-07 19:43:10

标签: neo4j cypher

我目前正在开始使用Neo4J及其查询语言cypher。 我有多个查询遵循相同的模式。

我正在对SQL数据库和Neo4J进行一些比较。

在我的Neo4J数据库中,我有一种标签(人)和一种关系(FRIENDSHIP)。该人具有propetyies personID,姓名,电子邮件,电话。 现在我想拥有第n个学位的朋友。我也想过滤掉那些也是学历较低的朋友。 举个例子,如果我想搜索3度的朋友,我想过滤掉那些也是朋友第一和/或第二学位的朋友。

这是我的查询类型:

MATCH (me:person {personID:'1'})-[:FRIENDSHIP*3]-(friends:person)
WHERE NOT (me:person)-[:FRIENDSHIP]-(friends:person)
AND NOT (me:person)-[:FRIENDSHIP*2]-(friends:person)
RETURN COUNT(DISTINCT friends);

我在某处找到了类似的东西。

此查询有效。

我的问题是,如果我寻求更高程度的友谊和/或如果人数变得更多,这种查询模式会慢得多。

所以我真的很感激,如果有人可以帮我优化这个。

2 个答案:

答案 0 :(得分:1)

如果你只想处理3的深度,这应该返回距离3度但不小于3度的不同节点:

MATCH (me:person {personID:'1'})-[:FRIENDSHIP]-(f1:person)-[:FRIENDSHIP]-(f2:person)-[:FRIENDSHIP]-(f3:person)
RETURN apoc.coll.subtract(COLLECT(f3), COLLECT(f1) + COLLECT(f2) + me) AS result;

上述查询使用APOC函数apoc.coll.subtract从结果中删除不需要的节点。该函数还确保集合包含不同的元素。

以下查询更通用,并且应该适用于任何给定深度(仅通过替换*之后的数字)。例如,此查询的深度为4:

MATCH p=(me:person {personID:'1'})-[:FRIENDSHIP*4]-(:person)
WITH NODES(p)[0..-1] AS priors, LAST(NODES(p)) AS candidate
UNWIND priors AS prior
RETURN apoc.coll.subtract(COLLECT(DISTINCT candidate), COLLECT(DISTINCT prior)) AS result;

答案 1 :(得分:0)

Cypher的可变长度关系匹配问题在于它正在寻找到该深度的所有可能路径。当你感兴趣的是某些深度的节点而不是它们的路径时,这会导致不必要的性能问题。

APOC's path expander使用' NODE_GLOBAL' uniqueness是一种更有效的方法,可以在包含深度的节点上进行匹配。

使用' NODE_GLOBAL'唯一性,节点在遍历期间只访问过一次。因此,当我们将路径扩展器的minLevelmaxLevel设置为相同时,结果是该级别的节点不存在于任何较低级别,这正是结果你想要得到。

安装APOC后尝试此查询:

MATCH (me:person {personID:'1'})
CALL apoc.path.expandConfig(me, {uniqueness:'NODE_GLOBAL', minLevel:4, maxLevel:4}) YIELD path
// a single path for each node at depth 4 but not at any lower depth
RETURN COUNT(path)

当然,当你有机会时,你想要参数化你的输入(personID,level)。