在neo4j中查询大型节点列表的最佳方法

xmd2e60i  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(166)

我尝试使用py2neo模块来执行以下操作,以获取neo4j数据库中大量节点的信息,这些节点的id已经知道:

query = f'''    
    MATCH 
        (n:MY_LABEL)
    OPTIONAL MATCH 
        (n) -- (u:OTHER_LABEL) // Won't always have a neighbor
    WHERE 
        id(n) in [{','.join(very_long_list_of_nids)}]
    RETURN 
        id(n) as nid, 
        n.feature1,
        u.feature2
'''
resp = graph.run(query)

字符串
我注意到,省略WHERE子句,并在返回每个n:MY_LABEL节点的内容后进行过滤要快得多。有没有更优雅的方式来做到这一点?
作为参考,very_long_list_of_nodes列表大约有500k个元素长(我曾尝试将其批处理成更小的10k块,也遇到了同样的问题),数据库包含4m个节点和10m条边。

db2dz4w8

db2dz4w81#

您应该:
1.将WHERE子句移到MATCH子句的正下方。目前,您的WHERE子句位于OPTIONAL MATCH子句下,因此只有找到所有MY_LABEL节点的关系后才能进行ID过滤。
1.从MATCH子句中删除:MY_LABEL限定。如果已经通过native ID获取节点,则不需要检查标签;而且你没有使用索引。
1.将ID列表作为parameter传递。这将使Cypher查询规划器运行得更快(因为Cypher代码很简单),一旦创建了计划,它将被缓存并在每次使用新的ID列表重新运行查询时重用。这也使您的客户端代码更简单,更快。
这应该更快:

query = f'''
    MATCH 
        (n)
    WHERE 
        ID(n) in $id_list
    OPTIONAL MATCH 
        (n) -- (u:OTHER_LABEL) // Won't always have a neighbor
    RETURN 
        ID(n) as nid, 
        n.feature1,
        u.feature2
'''
resp = graph.run(query, id_list=very_long_list_of_nids)

字符串
此外,如果MY_LABELOTHER_LABEL之间的关系总是单向流动,则应考虑在OPTIONAL MATCH子句中使用定向关系模式(--><--),特别是当MY_LABEL节点具有其他类型的反向流动关系时。

相关问题