首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用匹配与多个子句导致奇数结果

使用匹配与多个子句导致奇数结果
EN

Stack Overflow用户
提问于 2015-04-03 15:59:46
回答 2查看 79关注 0票数 2

我正在用Neo4j 2.0.4编写一个Cypher查询,该查询试图获取所选节点的入站和出站关系总数。当我只在同一时间使用这个查询时,我可以很容易地做到这一点,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:someIndex{name:"name1"})
MATCH g1-[r1]-()
RETURN count(r1);
//Returns 305

MATCH (g2:someIndex{name:"name2"})
MATCH g2-[r2]-()
RETURN count(r2);
//Returns 2334

但是,当我尝试用两个节点一起运行查询(即获得g1和g2的关系总数)时,我似乎得到了一个奇怪的结果。

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:someIndex{name:"name1"}), (g2:someIndex{name:"name2"})
MATCH g1-[r1]-(), g2-[r2]-()
RETURN count(r1)+count(r2);
//Returns 1423740

由于某种原因,这个数字比305+2334的总数大得多。

似乎其他Neo4j用户在使用多个MATCH子句时遇到了奇怪的问题,因此我阅读了Michael在https://groups.google.com/d/msg/neo4j/7ePLU8y93h8/8jpuopsFEFsJ上的解释,该解释建议Neo4j用户使用WITH来传递一次匹配的结果,以避免“标识符唯一性”。但是,当我运行以下查询时,它只是超时:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:gene{name:"SV422_HUMAN"}),(g2:gene{name:"BRCA1_HUMAN"})
MATCH g1-[r1]-()
WITH r1
MATCH g2-[r2]-()
RETURN count(r1)+count(r2);

我怀疑这个查询不会返回,因为r1返回了很多记录。在这种情况下,如何在两个节点上操作“获取关系号”查询?我只是使用了一些不正确的语法,还是我的“每次2节点”查询的逻辑存在一些根本问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-03 16:40:06

您的第一个问题是,当您这样做时,您正在返回一个笛卡儿产品:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:someIndex{name:"name1"}), (g2:someIndex{name:"name2"})
MATCH g1-[r1]-(), g2-[r2]-()
RETURN count(r1)+count(r2);

如果有305个r1实例和2334个r2实例,则返回(3052334) == 711870行,并且由于要对此(count(r1)+count(r2))求和,总共将得到711870 + 711870 == 1423740。

第二个问题是,在这个查询的g2子句中,您没有携带WITH

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:gene{name:"SV422_HUMAN"}),(g2:gene{name:"BRCA1_HUMAN"})
MATCH g1-[r1]-()
WITH r1
MATCH g2-[r2]-()
RETURN count(r1)+count(r2);

您在第一个g2子句中匹配MATCH,但是当您只在第3行的WITH子句中传递r1时,就会留下它。然后,在第4行,当您在g2-[r2]-()上匹配时,您将匹配图形中的所有内容,因为g2已经解除绑定。

让我介绍一下Neo4j浏览器附带的电影数据集的解决方案,因为您还没有提供示例数据。比方说,我想知道汤姆·汉克斯和雨果·韦文的关系总数。

作为单独的查询:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:Person {name:'Tom Hanks'})-[r]-()
RETURN COUNT(r)

=> 13

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:Person {name:'Hugo Weaving'})-[r]-()
RETURN COUNT(r)

=> 5

如果我试图按您的方式来做,我将得到(13 * 5) *2 == 90,这是不正确的:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:Person {name:'Tom Hanks'})-[r1]-(), 
      (:Person {name:'Hugo Weaving'})-[r2]-()
RETURN COUNT(r1) + COUNT(r2)

=> 90

同样,这是因为我已经在r1r2的所有组合上进行了匹配,其中有65 (13 *5 == 65),然后将其加到总共90 (65 + 65 == 90)。

解决方案是使用DISTINCT

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:Person {name:'Tom Hanks'})-[r1]-(), 
      (:Person {name:'Hugo Weaving'})-[r2]-()
RETURN COUNT(DISTINCT r1) + COUNT(DISTINCT r2)

=> 18

显然,DISTINCT修饰符只计算每个实体的不同实例。

如果您需要,还可以使用WITH完成此任务:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:Person {name:'Tom Hanks'})-[r]-()
WITH COUNT(r) AS r1
MATCH (:Person {name:'Hugo Weaving'})-[r]-()
RETURN r1 + COUNT(r)

=> 18

笛卡尔产品的TL;DR。DISTINCT是你的朋友:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (:someIndex{name:"name1"})-[r1]-(), 
      (:someIndex{name:"name2"})-[r2]-()
RETURN COUNT(DISTINCT r1) + COUNT(DISTINCT r2);
票数 3
EN

Stack Overflow用户

发布于 2015-04-03 16:40:08

你所看到的结果的爆炸可以很容易地解释:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g1:someIndex{name:"name1"}), (g2:someIndex{name:"name2"})
MATCH g1-[r1]-(), g2-[r2]-()
RETURN count(r1)+count(r2);
//Returns 1423740

在第2行中,来自g1的任何关系的每一个组合都与g2的任何关系相结合,这解释了自1423740 =3052334*2以来的数字。所以,你基本上是在评估一个交叉乘积。

计算name1name2所有关系之和的正确方法是:

代码语言:javascript
代码运行次数:0
运行
复制
MATCH (g:someIndex)-[r]-()
WHERE g.name in ["name1", "name2"]
RETURN count(r)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29435590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档