Cypher查询匹配强大的双向关系,并按Neo4j中的属性值进行过滤

时间:2013-01-04 13:52:23

标签: database nosql neo4j cypher

我想在Neo4j DB中找到一个只有很强的双向关系的子图。

假设关系是LOVES,属性是Kisses,那么我只想找到一个子图,其中双方已经吻了2次以上。

START n=node(*)
MATCH n-[r1:LOVES]->friend<-[r2:LOVES]-n
WHERE r1.Kisses > 2 and r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

问题是该查询似乎永远在3M节点30M关系图上运行,在32GB RAM,四核系统上,neo4j最大堆为16GB(neo4j计算器建议8GB)。

我怀疑,隐藏在某个地方的无限循环。

OS:Ubuntu 12.04.1 LTS服务器

Soft:neo4j-community-1.8.1

java版“1.7.0_10”(neo4j start表示使用JDK6)

Java(TM)SE运行时环境(版本1.7.0_10-b18)

Java HotSpot(TM)64位服务器VM(版本23.6-b04,混合模式)

编辑:匹配不正确应该是

MATCH n-[r1:LOVES]->friend-[r2:LOVES]->n

更新:   在纠正上面的语义之后,我仍然无法在5分钟内得到完整的结果。

LOVES是唯一的关系类型,约10-20%,或者关系有相应的关系。

我的最终目标是找到合适的Kiss值,以便我留下&lt; 100k节点(以及所有适当的LOVES关系)并且可以导出这个子图。

这是我想要做的算法的伪代码:

let E be edge.list to be processed
let myedgelist be empty list
for e in E:
  if e.n1 > e.n2: # so we do not look twice
    continue
  if not exist(e[n2][n1]): # this is where lookup can be a problem O(1) for hash, O(logn) for sorted, O(n) for something random)
    continue
  if e.kisses > 2 and e[n2][n1].kisses > 2:
    add e to myedgelist
    add e[n2][n1] to myedgelist
return myedgelist

此算法最多应运行edgecount * log(edgecount),除非在neo4j中没有有效的方法来查找反向关系的存在,这似乎是不可思议的。

2 个答案:

答案 0 :(得分:1)

你应该在1.9中尝试这个 - cypher matcher已针对此类查询进行了显着优化。虽然避免节点(*)会很好。您的所有节点都是人吗?如果不是,您可能希望进行索引查询以仅获取相关人员节点。

start n=node:people("name:*") ...

答案 1 :(得分:1)

您可以尝试将friend设为目标节点

START friend=node(*)
MATCH n-[r1:LOVES]->friend-[r2:LOVES]->n
WHERE r1.Kisses > 2 and r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

你可以尝试将比赛分成两部分

START n=node(*)
MATCH n-[r1:LOVES]->friend
WHERE r1.Kisses > 2
WITH n,r1,friend
MATCH n<-[r2:LOVES]-friend
WHERE r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

或者仅使用匹配执行查询的一半而使用过滤器执行后半部分

START n=node(*) 
MATCH n-[r1:LOVES]->friend 
WHERE r1.Kisses > 2 
 AND ALL(r2 in extract(
              p in friend-[:LOVES]->n : head(rels(p))) 
         WHERE r2.Kisses > 2) 
RETURN n, friend, r1
LIMIT 20

这是一个试用查询的控制台:http://console.neo4j.org/r/tqvb1p

但毕竟你正在处理3M节点,其匹配可能会爆炸到3M ^ 2