Neo4j Cypher/我应该使用WITH子句将值传递给下一个匹配项吗?
使用Neo4j 2.1.X,让我们假设以下查询,返回用户123购买汽车的朋友:Neo4j Cypher/我应该使用WITH子句将值传递给下一个匹配项吗?,neo4j,cypher,Neo4j,Cypher,使用Neo4j 2.1.X,让我们假设以下查询,返回用户123购买汽车的朋友: MATCH (u1:User("123"))-[:KNOWS]-(friend) MATCH (friend)-[:BUYS]->(c:Car) RETURN friend 在此,它是关于WITH子句编写的: 那么,它是如何工作的呢?嗯,with基本上只是一个流,就像lazy一样 尽可能地(尽可能地懒惰),将结果传递给 下一个查询 因此,我似乎应该这样转换查询: MATCH (u1:User("123"))-
MATCH (u1:User("123"))-[:KNOWS]-(friend)
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend
在此,它是关于WITH
子句编写的:
那么,它是如何工作的呢?嗯,with基本上只是一个流,就像lazy一样
尽可能地(尽可能地懒惰),将结果传递给
下一个查询
因此,我似乎应该这样转换查询:
MATCH (u1:User("123"))-[:KNOWS]-(friend)
WITH friend
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend
我应该吗?或者当前版本的Cypher在传递值时是否已经处理了
匹配
链接?在查询的前面给出的起点越准确,效率就越高
您的第一个匹配不是那么精确,实际上它将使用遍历匹配器来匹配所有可能的关系
以以下neo4j控制台为例:
MATCH (n:User { login: 'nash99' })-[:KNOWS]->(friend)
RETURN count(*)
在示例中,您的第一个查询是谁:
MATCH (n:User { login: 'nash99' })-[:KNOWS]->(friend)
RETURN count(*)
您可以在前面看到数据库点击量:
Execution Plan
ColumnFilter
|
+EagerAggregation
|
+Filter
|
+TraversalMatcher
+------------------+------+--------+-------------+-----------------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+------------------+------+--------+-------------+-----------------------------------------+
| ColumnFilter | 1 | 0 | | keep columns count(*) |
| EagerAggregation | 1 | 0 | | |
| Filter | 8 | 320 | | Property(n,login(2)) == { AUTOSTRING0} |
| TraversalMatcher | 160 | 201 | | friend, UNNAMED32, friend |
+------------------+------+--------+-------------+-----------------------------------------+
Total database accesses: 521
如果使用更精确的起点,从该点开始,您就是道路之王,请查看此示例查询,并查看db命中率的差异:
Execution Plan
ColumnFilter
|
+EagerAggregation
|
+SimplePatternMatcher
|
+Filter
|
+NodeByLabel
+----------------------+------+--------+------------------------+-----------------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+----------------------+------+--------+------------------------+-----------------------------------------+
| ColumnFilter | 1 | 0 | | keep columns count(*) |
| EagerAggregation | 1 | 0 | | |
| SimplePatternMatcher | 8 | 0 | n, friend, UNNAMED51 | |
| Filter | 1 | 40 | | Property(n,login(2)) == { AUTOSTRING0} |
| NodeByLabel | 20 | 21 | n, n | :User |
+----------------------+------+--------+------------------------+-----------------------------------------+
Total database accesses: 61
MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)
WITH friend
MATCH (friend)-[:BUYS)->(c:Car)
RETURN (friend)
因此,要终止您的查询,我将执行以下操作:
MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)-[:BUYS]->(c:Car)
RETURN friend
您还可以指定好友不能与用户相同:
MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)-[:BUYS]->(c:Car)
WHERE NOT friend.id = n.id
RETURN friend
请注意,在db命中率方面,上述查询与以下查询没有区别:
Execution Plan
ColumnFilter
|
+EagerAggregation
|
+SimplePatternMatcher
|
+Filter
|
+NodeByLabel
+----------------------+------+--------+------------------------+-----------------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+----------------------+------+--------+------------------------+-----------------------------------------+
| ColumnFilter | 1 | 0 | | keep columns count(*) |
| EagerAggregation | 1 | 0 | | |
| SimplePatternMatcher | 8 | 0 | n, friend, UNNAMED51 | |
| Filter | 1 | 40 | | Property(n,login(2)) == { AUTOSTRING0} |
| NodeByLabel | 20 | 21 | n, n | :User |
+----------------------+------+--------+------------------------+-----------------------------------------+
Total database accesses: 61
MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)
WITH friend
MATCH (friend)-[:BUYS)->(c:Car)
RETURN (friend)
我建议您使用neo4j控制台查看显示上述信息的结果详细信息
如果需要为测试快速原型化图形,可以使用Graphgen,在cypher语句中导出图形,并在neo4j控制台中加载这些语句
下面是我用于控制台的graphgen一代的链接
克里斯我的询问出错了。它应该是:
MATCH(u1:User{id:“123”})-[:KNOWS](friend)
。你写道:“你的第一场比赛不太准确。”。为什么?因为我使用的是一个带有id
属性索引的标签……是的,您使用的是标签,但是您没有匹配一个标签化的节点,而是一个完整的模式。看看结果细节,它正在使用遍历匹配器,因此它将遍历图形以匹配您的模式,根据我的建议,它正在使用标签索引,而不是使用标签索引。。。我认为这种行为应该是:“第一个节点被标记,所以我(密码引擎)首先匹配它,然后,我将遍历指定的路径”。如果我能很好地理解的话,您的意思是,在我的情况下,这种行为是:“让我们遍历路径,我只保留与索引匹配的节点”…显然会导致完全遍历匹配。我明白了吗?不,你可以,你应该,问题是你没有定义一个特定的起点。如果你把你对Cypher说的话翻译成“hey find me所有可能的与type KNOWS的关系都连接到用户123”,你最好这样说“嘿,Cypher,使用标签索引找到我用户123,然后从这个用户找到与我连接的所有关系KNWOS。不,我不认为有这样的文档,也许neo4j网站上的一些食谱会有所帮助。我建议您使用neo4j控制台和结果详细信息,这对于理解Cypher如何处理查询非常有帮助。查看stackoverflow的问题和答案,以及来自顶尖人物的博客帖子,如迈克尔·霍恩、肯尼·巴斯塔尼、妮可·怀特、弗罗博比特、约翰·马克18、马克·李约瑟、格拉帕瓦、奈杰尔·斯莫尔,我肯定会超过一些人。还可以查看Neo4j谷歌集团。不要犹豫,你正在帮助你和人们寻找相同的答案。