neo4j-改善Cypher查询

时间:2018-10-14 18:44:51

标签: python graph neo4j cypher

我有一个性能至关重要的应用程序,该应用程序必须基于正则表达式匹配将多个节点与另一个节点进行匹配。我当前的查询如下:

MATCH (person: Person {name: 'Mark'})
WITH person
UNWIND person.match_list AS match
MATCH (pet: Animal) 
WHERE pet.name_regex =~ match
MERGE (person)-[:OWNS_PET]->(pet) 
RETURN pet

但是,此查询的运行速度非常慢(在我的工作站上大约500毫秒)。 该图包含大约50万个节点,大约1万个将与正则表达式匹配。

我想知道是否有更有效的方法来重新编写此查询以使其同样工作,但可以提高性能。

编辑:

当我在多个Persons多线程上运行此查询时,出现TransientError异常

neo4j.exceptions.TransientError: ForsetiClient[3] can't acquire ExclusiveLock{owner=ForsetiClient[14]} on NODE(1889), because holders of that lock are waiting for ForsetiClient[3].

编辑2:

Person:name是唯一的并已编入索引

Animal:name_regex未编入索引

1 个答案:

答案 0 :(得分:2)

首先,我将首先尽可能简化您的查询。找到匹配后,您的工作方式现在会浪费很多精力

MATCH (person: Person {name: 'Mark'}), (pet: Animal)
WHERE ANY(match in person.match_list WHERE pet.name_regex =~ match)
MERGE (person)-[:OWNS_PET]->(pet) 
RETURN pet

这样可以做到,如果有多个匹配项,则仅尝试进行1次合并,一旦找到一个匹配项,将不再尝试对同一只宠物进行其余的合并。这也使Cypher可以对数据进行最大程度的优化。

要进一步改善密码,您将需要优化数据。例如,正则表达式匹配非常昂贵(需要进行节点+字符串扫描),如果可以在人与人之间大量重复使用match语句,则最好将它们分解成一个节点,然后连接到那些节点上,以便一个人的工作regex匹配可以在任何重复的地方重复使用。