如果属性数大于n,则从Neo4j中的高度连接图返回

时间:2016-04-21 19:28:52

标签: graph neo4j cypher

此问题是我之前询问的问题here(甚至更早版本here)的直接扩展。

假设我有一个如下所示的图形数据库:

enter image description here

就像我之前提出的问题一样,唯一真正有趣的是SomeProperty可以是'是'或'否'。

在第一行中,三个节点中的一个对此属性具有“是”。

在底行,五个节点中的3个节点对此属性具有“是”。

轻微的哲学旁注:我开始怀疑这是一个糟糕的图形模式。为什么?因为,在每组节点中,每个节点都连接到每个其他节点。我我并不担心有两组节点这一事实,但事实上,当我填充这个图时,我会得到说话,'返回530行'。我认为这意味着实际上在图结构中创建了530个子路径,这看起来有点矫枉过正。)

无论如何,我试图解决的问题与我试图在更早,更简单,更线性的上下文here中解决的问题几乎相同。

我想返回这些不相交图中的任何一个的完整路径,而在所述图中的任何位置,SomeProperty的出现次数大于2。

我认为这是一个常见的简单问题。例如,假设你有两个不相关的家庭,有人说,“让我和家人在一起有两个以上的左撇子。”

超级聪明的#cybersam建议更简单地体现这个问题,这有点像:

MATCH p=(a:person)-[:RELATED_TO*]->(b:person)
WHERE
  NOT ()-[:RELATED_TO]->(a) AND
  NOT (b)-[:RELATED_TO]->() AND
  2 < REDUCE(s = 0, x IN NODES(p) | CASE WHEN x. SomeProperty = 'Yes' THEN s + 1 ELSE s END)
RETURN p;

...如果图形更像是一条直线,并且没有集合中的每个节点与每个其他节点相关,那么它的效果很好。

我认为#cybersam的查询无法处理这个更复杂的图表的原因是因为没有终端节点。

另一个哲学旁注:我开始提出一种理论,即图形中密集,错综复杂的关系会带来组合问题,性能和查询。我认为这可能是应有的查询时Cypher使用的双向性?)

这是我的数据。任何建议都表示赞赏,感谢您帮助我攀登学习曲线。

// match (n) detach delete n;

CREATE (albert:person {gender: 'Male', name: 'Albert', SomeProperty: 'Yes'})
CREATE (annie:person {gender: 'Female', name: 'Annie', SomeProperty: 'No'})
CREATE (adrian:person {gender: 'Female', name: 'Adrian', SomeProperty: 'No'})

CREATE (albert)-[:RELATED_TO]->(annie)
CREATE (annie)-[:RELATED_TO]->(albert)
CREATE (annie)-[:RELATED_TO]->(adrian)
CREATE (adrian)-[:RELATED_TO]->(annie)
CREATE (albert)-[:RELATED_TO]->(adrian)
CREATE (adrian)-[:RELATED_TO]->(albert)


CREATE (bill:person {gender: 'Male', name: 'Bill', SomeProperty: 'Yes'})
CREATE (barb:person {gender: 'Female', name: 'Barb', SomeProperty: 'Yes'})
CREATE (barry:person {gender: 'Male', name: 'Barry', SomeProperty: 'Yes'})
CREATE (bart:person {gender: 'Male', name: 'Bart', SomeProperty: 'No'})
CREATE (bartholemu:person {gender: 'Male', name: 'Bartholemu', SomeProperty: 'No'})

CREATE (bill)-[:RELATED_TO]->(barb)
CREATE (barb)-[:RELATED_TO]->(bill)
CREATE (barb)-[:RELATED_TO]->(barry)
CREATE (barry)-[:RELATED_TO]->(barb)
CREATE (barry)-[:RELATED_TO]->(bart)
CREATE (bart)-[:RELATED_TO]->(barry)
CREATE (bart)-[:RELATED_TO]->(bartholemu)
CREATE (bartholemu)-[:RELATED_TO]->(bart)
CREATE (bill)-[:RELATED_TO]->(bartholemu)
CREATE (bartholemu)-[:RELATED_TO]->(bill)

1 个答案:

答案 0 :(得分:1)

如果这是关于人的家庭,那么最简单的解决方法是为每个关系组添加一个:Family节点,如下所示:

create (f:Family) with f 
match (a:person {name:"Adrian"})-[:RELATED_TO*]->(b:person)  
merge (f:Family)<-[:FAMILY]-(a) 
merge (f:Family)<-[:FAMILY]-(b)

将“Adrian”改为“Barry”以创建第二个家庭组。

这为您提供了一个核心:每个家庭组的家庭节点。然后你可以选择有足够的家庭组:person.SomeProperty =“是”家庭成员如此:

// Find families with 2 or more :person.SomeProperty = "yes"
match p = (f:Family)<-[:FAMILY]-(psn:person)
where psn.SomeProperty = "Yes"
with  f, count(psn) as cnt 
where cnt > 2

// Get the family members 
match (a:person)<-[r1:RELATED_TO]-(b:person)-[r2:RELATED_TO*]->(c)
where (a)-[:FAMILY]-(f)
  and a = c  // to get all the nodes in the loop 

// report the first record which'll have two  
// family members and all the relationships
return a, r1, b, r2 
limit 1