【问题标题】:How to perform sub pattern matches with neo4j.Apoc?如何使用 neo4j.Apoc 执行子模式匹配?
【发布时间】:2019-08-20 20:14:07
【问题描述】:

我有疑问:

MATCH (a:vertex {label: 'a'})<-->(b:vertex {label: 'b'})
MATCH (a)<-->(e:vertex {label: 'e'})
MATCH (b)<-->(c:vertex {label: 'c'})
MATCH (b)<-->(e:vertex {label: 'e'})
MATCH (c)<-->(d:vertex {label: 'd'}) 
MATCH (d)<-->(e)
MATCH (d)<-->(a)
return a,b,c,d,e

还有一个由 50.000 个顶点和 10.000.000 条边组成的图。 它总共只有标签 a,b,c,d,e,f,我知道这个匹配存在。

我已经安装了neo4j.apoc 插件以利用我机器上的 8 个内核,并且我已经尝试了以下查询:

CALL apoc.periodic.iterate(
"MATCH (a:vertex {label: 'a'})<-->(b:vertex {label: 'b'})
MATCH (a)<-->(e:vertex {label: 'e'})
MATCH (b)<-->(c:vertex {label: 'c'})
MATCH (b)<-->(e:vertex {label: 'e'})
MATCH (c)<-->(d:vertex {label: 'd'}) 
MATCH (d)<-->(e)
MATCH (d)<-->(a)
return a,b,c,d,e",
"return DISTINCT([ID(a),ID(b),ID(c),ID(d),ID(e)]) AS LIST", {batchSize:10000, parallel:true})

这个查询只使用了几个核心,它基本上从不返回结果,它只是永远处理。我一直在看 函数apoc.path.subgraphAll(startNode &lt;id&gt;Node/list, {maxLevel, relationshipFilter, labelFilter, bfs:true, filterStartNode:true, limit:-1}) yield nodes, relationships

但由于我对 NEO4J 和 Apoc 非常陌生,所以我实际上不明白如何填写这些关系。有没有人知道这些东西并且可以指出我正确的方向?

编辑:我有一个自定义的 java 图形实现,它并行执行并在大约 600 毫秒内完成,我希望 NEO4J 能够更快地完成它,但是由于查询只使用 1 个线程,因此需要很长时间,这这就是我一直在研究 Apoc 的原因。我也愿意使用 Apoc 以外的其他东西,也许我的查询可以仅使用 NEO4J 进行优化并更快地完成。我在 :vertex(label) 上创建了一个索引,所以至少该部分会进行索引搜索。

编辑2: 这个查询应该做同样的事情,而且显然更漂亮:

CALL apoc.periodic.iterate(
"MATCH (a:vertex {label:'a'})--(b:vertex {label: 'b'})--(c:vertex {label: 'c'})--(d:vertex {label: 'd'})--(e:vertex {label: 'e'}) WHERE (c)<-->(d) AND (b)--(e) AND (d)--(a) 
RETURN a,b,c,d,e",
"return DISTINCT([ID(a),ID(b),ID(c),ID(d),ID(e)]) AS LIST", {batchSize:10000, parallel:true})

但它仍然从未停止处理,我什至将图形调整为 10k 个顶点和 500 万条边。

【问题讨论】:

    标签: neo4j pattern-matching neo4j-apoc


    【解决方案1】:

    我不需要 Apoc,我误解了密码语法,我认为 (a)(b) 意味着 a 和 b 需要双向关系。但实际上只是匿名关系。 所以我把它优化成这样:

    MATCH (a:vertex {label:'a'})-->(b:vertex {label: 'b'})-->(c:vertex {label: 'c'})-->(d:vertex {label: 'd'})-->(e:vertex {label: 'e'}) WHERE (d)-->(a) AND (b)-->(e) AND (d)-->(e)  WITH a,b,c,d,e
    MATCH (a)<--(b)<--(c)<--(d)<--(e:vertex {label: 'e'}) WHERE (d)<--(a) AND (b)<--(e) AND (d)<--(e)  WITH a,b,c,d,e
    return DISTINCT([ID(a),ID(b),ID(c),ID(d),ID(e)])
    

    为了过滤指向两个方向的边,使查询计划中的估计行数大大降低,现在在 12000 毫秒内完成

    【讨论】:

    • 你可以减少一些事情,因为你的一些检查已经被你的比赛完成了。在第一行,AND (d)--&gt;(e) 可以被删除,这在你的 MATCH 模式中被捕获。在第二行中,您不需要 (e:vertex {label: 'e'}),因为它已经从您之前的 MATCH 到 e 建立。只需在该模式的末尾使用(d)&lt;--(e)。在 WHERE 子句中,您可以删除 AND (d)&lt;--(e),因为这已经在 MATCH 中处理了。当然,请确保您在 :vertex(label) 上有一个索引
    • Arg 是的,当然,我的扳机速度太快了 :) 谢谢!
    猜你喜欢
    • 1970-01-01
    • 2010-10-22
    • 2011-01-17
    • 1970-01-01
    • 2012-07-14
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多