2017-04-25 219 views
0

我努力学习Cypher和我有一个trust network的数据,我想查询谁相信“15最信任的人”的人,所以我写了这个查询,QUERY1:为什么这两个Cypher查询返回不同的结果?

QUERY1: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id}) 
return w1.Id as user1, w2.Id as user2 

,我以后想要将最后两行查询更改为:

QUERY2: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 
return w1.Id as user1,w2.Id as user2, w3.Id as user3 

并且在分析结果后,我猜测有什么不对! 所以我硬编码id到特定的值,例如575,然后count(p)等于1937520,但是,如果我运行硬编码ID查询的最后一行,作为一个独立的查询:

QUERY3: 

MATCH r=(u1:USER)-[:TRUST]->(u2:USER {Id: "575"})-[:TRUST]->(u3:USER) 
return count(r) 

count(r)等于到129168!

我检查了用户“575”信任207人并且被624人信任,所以QUERY3结果似乎是正确的:207 * 624 = 129168。我的问题是为什么?! 我不明白QUERY2有什么问题,第二个问题是否意味着QUERY1结果也是错误的?

EDIT1: 感谢的答案,但我仍然有这个问题,所以我检查了另一个场景,我已经得到了以下结果: 如果我写这样的查询:

QUERY4: 
MATCH (n) WITH n limit 15 return "1" 

我将在输出中打印15“1”,所以这意味着QUERY2的最后一部分执行15次,无论我是否对Id进行硬编码,就像它在for循环中一样。所以这里的问题是,我认为WHIT X LIMIT N doSomeThing将像foreach(x : X)循环执行,如果我使用x,并且不会,如果我不使用x。愚蠢的假设...

回答

1

在QUERY3中,您将u2与单个用户(用户575)相匹配。 QUERY 3是正确的。

但是,在QUERY2中,WITH(第3行)与15个不同的u1-u2组合相匹配。 MATCH(第1行)为每个u1和u2返回一个“行”,这与该模式相匹配。那么你只返回前15个结果,我猜是15个不同的u1 u2 = user {Id:575}这就是给出1937520个结果,这正好是15 * 129168.

问题在with出现是因为你没有聚合(每个u2只得到1行)。你为每个u2用户'返回'(使用WITH)一个id变量,所以count(u2)将永远是1.也许你想写u1.Id或count(u1)?无论如何,由于LIMIT 15(第4行),使用u2.Id或u1.Id将返回15个结果。 LIMIT 1会做的伎俩,但我们也可以这样做:

MATCH (u1:User)-[:TRUST]-(u2:User) 
WITH DISTINCT(u2.Id) AS id 
LIMIT 15 

然后是QUERY2的其余部分(或QUERY1,对于这个问题)。我取消了分数变量,但是如果它意味着计数(u1),它可以被读取而没有问题。

+0

你是对的,但如果我改变(W2:用户{ID:ID})QUERY2的一部分(W2:用户{ID: “575”})我得到1937520结果,不这意味着最后一个匹配部分为USER“575”运行15次,因为限制15? –

+0

谢谢,我编辑了答案来反映这一点。问题在于WITH上缺少DISTINCT,导致查询多次返回同一用户。 – yawmoght

1

此查询可能会做你想要的。

MATCH (:USER)-[r:TRUST]->(u2:USER) 
WITH u2, COUNT(r) AS score 
ORDER BY score DESC 
LIMIT 15 
MATCH (w1:USER)-[:TRUST]->(u2)-[:TRUST]->(w3:USER) 
RETURN w1.Id AS user1, u2.Id AS user2, w3.Id AS user3; 

它首先找到15个最信任的用户,然后找到所有这些用户都在中间的2级信任路径,最后返回这些路径的用户的ID。

另外,第二个MATCH重复使用第一个MATCH已经找到的u2节点,以加速处理第二个MATCH

1

我只是打破查询2,其余的应该是有道理的。

QUERY2: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 
return w1.Id as user1,w2.Id as user2, w3.Id as user3 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 

你基本上创建所有U1信托U2的启动列表;和COUNT(u2)= u2的#匹配。因此,假设u1相信u2有100个匹配项,COUNT(u2)会为每一行在该列中放置'100'。 (然后你为了什么现在是一个常量,它什么也不做,并限制15,所以你现在有15 U1信托U2的任意列表。

使刚刚离开

match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 

使匹配用户w1信任用户w2的每个路径p(用于每个用户的id),并相信用户w3。

因此,修复第一部分,以获得'前15个可信用户,你需要统计传入信托的数量

MATCH (u1:USER)-[trusts:TRUST]->(u2:USER) 
with u2, COUNT(trusts) AS score 
order by score desc 
limit 15 

所以现在你有15个最值得信赖的用户,你可以用return u2.id, score来验证这一点。为了让谁相信这些人,你会比只需要问这样的人......

MATCH (u3:USER)-[:TRUST]->(u2) 

,然后U3会是谁信任来自排名前15位信任的人(U2)一个人的所有用户。

作为一个额外的注意,如果您使用的是Neo4j的Web浏览器,尝试配置文件关键字您的CYPHER一些洞察到什么暗号查询实际执行前挂起。

编辑1:

我们解释一下查询4确实MATCH (n) WITH n limit 15 return "1"。正如我相信你一定猜到了,MATCH (n) WITH n limit 15比赛的所有节点,但结果限制到第一15.在返回部分,你说:“对于每一行,返回常量‘1’。”,这给你内部15个不同行,但返回的行不明显。这是DISTINCT关键字的用途。使用RETURN DISTINCT“1”表示“对于每一行,返回常量'1',但过滤结果集只有不同的行。”又如,没有2列将具有相同的价值。如果你知道会有一些重复的行,但要看到他们反正(也许对于一个重量的参考,或知道他们是从2个独立的字段)的非明显的结果是有用的。

+0

谢谢,我从你的答案中学到了很多东西,为PROFILE关键字+1了,但是我的问题是其他问题。我在EDIT1中提到过它。 –

+0

@ M-N不确定查询4对您的问题实际上意味着什么,但是我添加了对查询4做什么的解释,以便您可以理解结果。 :3 – Tezra

0

正如我在EDIT1中提到的,这里的问题是我认为WHIT X LIMIT N doSomeThing将像foreach(x : X)循环一样执行,如果我使用x,并且不会,如果我不使用x。愚蠢的假设......

相关问题