2015-11-05 32 views
1

我在Neo4j上学习Cypher,并且在理解如何在Cypher中执行高效'连接'等效操作时遇到问题。Cypher在'join'返回指数计数结果

我正在使用标准的矩阵字符示例,并且我已经添加了一些名为'Gun'的混合节点,其关系为':GIVEN_TO'。您可以在控制台上看见我的查询结果的位置:

http://console.neo4j.org/r/rog2hv

我使用的查询是:

MATCH (Neo:Crew { name: 'Neo' })-[:KNOWS*..]->(other:Crew),(other)<-[:GIVEN_TO]-(g:Gun),(Neo)<-[:GIVEN_TO]-(g2:Gun) RETURN count(g2);

我已经给新4枪,但是当我执行上面的我得到'12'。这似乎是这种情况,因为有3个“其他”和3 * 4 = 12。所以我得到了一些指数结果。

我的查询应该如何从示例中获得正确的计数('4')?

编辑: 我不直接按照@ceej的建议直接查询枪炮的原因是因为在我的真实使用案例中,我必须如上所述进行遍历。添加DISTINCT不会为我的结果做任何事情。

回答

4

你得到12枪而不是4的原因是因为你的查询产生笛卡尔积。这是因为您已经在同一个匹配语句中询问了商品,但没有加入他们。 @ceej正确地指出,如果你想找到Neo的枪,你会按照他在第一个问询中所建议的那样去做。

如果你想获得的船员和他们的枪,那么你可以做这样的事情的清单...

MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun) 
RETURN crew.name, collect(g.name) 

指找到所有船员的枪,并返回他们的名字和他们得到的枪支。

如果你想反转,并得到了枪支和相应的机组成员,他们给你可以做下面的列表...

MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun) 
RETURN g.name, collect(crew.name) 

如果你想找到所有的船员知道Neo多层次的深度,那就是给你一把枪,你可以写下这样的查询......

MATCH (crew:Crew)<-[:GIVEN_TO]-(g:Gun) 
WITH crew, g 
MATCH (neo:Crew {name: 'Neo'})-[:KNOWS*0..]->(crew) 
RETURN crew.name, collect(g.name) 

即认定给予枪的所有船员,然后确定其中哪些有:KNOWS路径新。

+0

谢谢,已经接近我的实际使用案例,我认为这应该是更好的。现在我剩下的问题是,我将如何获得所有知道Neo深度的机组成员的实际枪支节点?所以那些认识Neo等人的人[':KNOWS * ..]'和:还可能包括那些船员节点? – Mosselman

+0

我设法在这里得到结果:http://console.neo4j.org/r/25or9h但它似乎不是实现这一目标的最佳方式。有什么想法吗? – Mosselman

+0

是的,还有更好的方法。我用另一个查询返回了答案,该查询返回了知道Neo的船员枪支。 –

2

原谅我,但我不清楚为什么你的查询中有最初的MATCH。从你的解释中可以看出,你试图通过:GIVEN_TO关系获得Neo链接的:Gun节点的数量。在这种情况下,您只需要查询的后半部分。这将使你像

MATCH (neo:Crew { name: 'Neo' })<-[:GIVEN_TO]-(g:Gun) 
RETURN count(g) 

此外,以确保您只计算不同:Gun节点可以添加DISTINCTRETURN声明。

MATCH (neo:Crew { name: 'Neo' })<-[:GIVEN_TO]-(g:Gun) 
RETURN count(DISTINCT g) 

这是你的情况可能是不必要的,但可能是有益的,当你在匹配上的图案可以由不同的遍历同一节点到达。

我误解了你的要求吗?

+0

在现实中,我并不想数枪。我试图得到所有船员和他们的枪的结果集。我之所以要通过计数并通过Neo认识的人来做这件事,是因为我想通过已知的联系人来获得正确的计数。我会在这个问题上试图更清楚地说明这一点。 – Mosselman