我正在尝试学习Cypher并且我拥有trust network的数据,我想查询信任的人和最可信赖的人",所以我写了这个查询, QUERY1:
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进行硬编码,就像它&# 39; s在for循环中。所以这里的问题是我认为WHIT X LIMIT N doSomeThing
会像foreach(x : X)
循环一样执行,如果我使用x,如果我不使用x则不会。愚蠢的假设...
答案 0 :(得分:1)
在QUERY3中,您将u2与单个用户(用户575)进行匹配。 QUERY 3是正确的。
然而,在QUERY2中,WITH(第3行)匹配15种不同的u1-u2组合。 MATCH(第1行)为每个u1和u2返回一个“行”,即井匹配该模式。然后你只返回前15个结果,我猜这是15个不同的u1为u2 =用户{Id:575}这就是给出1937520个结果,正好是15 * 129168。
出现问题因为你没有聚合(每个u2只获得1行)。你为每个u2用户'返回'(使用WITH)一个id变量,因此count(u2)将始终为1.也许你想写u1.Id或count(u1)?无论如何,有了u2.Id或u1.Id将因为LIMIT 15(第4行)而返回15个结果。 LIMIT 1可以解决问题,但我们也可以这样做:
MATCH (u1:User)-[:TRUST]-(u2:User)
WITH DISTINCT(u2.Id) AS id
LIMIT 15
然后是剩余的QUERY2(或QUERY1,就此而言)。我删除了得分变量,但如果它是计数(u1),则可以毫无问题地读取它。
答案 1 :(得分: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
重复使用第一个u2
已找到的MATCH
个节点,以加快第二个MATCH
的处理速度。
答案 2 :(得分: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)
这样就匹配每个路径p,其中用户w1信任用户w2(对于来自第一部分的每个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浏览器,请尝试将PROFILE关键字预先挂起到您的密码,以便深入了解密码查询实际执行的操作。
编辑1:
现在解释查询4的作用MATCH (n) WITH n limit 15 return "1"
。我确信你猜对了,MATCH (n) WITH n limit 15
匹配所有节点但是将结果限制在第15位。在RETURN部分,你说"对于每一行,返回常数' 1'。 ",它在内部为您提供15个不同的行,但返回的行不是不同的。这就是DISTINCT关键字的用途。使用RETURN DISTINCT" 1"说"对于每一行,返回常量' 1',但过滤结果集只有不同的行。"也就是说,没有2列将具有相同的值。如果你知道会有一些重复的行,但是你想要看到它们(可能是为了重量参考,或者知道它们来自2个不同的字段),那么非独特的结果很有用。
答案 3 :(得分:0)
正如我在EDIT1中提到的,这里的问题是我认为WHIT X LIMIT N doSomeThing
会像foreach(x : X)
循环一样执行,如果我使用x,如果我不这样做则不会用x。愚蠢的假设...