Cypher /我应该使用WITH子句将值传递给下一个MATCH吗?

时间:2014-10-19 18:45:15

标签: neo4j cypher

使用Neo4j 2.1.X,让我们假设这个查询,让用户123的朋友买回一辆车:

MATCH (u1:User("123"))-[:KNOWS]-(friend)
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend

在这个article中,它是关于WITH子句:

  

那么,它是如何运作的?好吧,基本上只是一个流,就像懒惰一样   因为它可以(像返回一样懒惰),将结果传递给   下一个查询。

所以看来我应该像这样转换查询:

MATCH (u1:User("123"))-[:KNOWS]-(friend)
WITH friend
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend
我应该吗?或者当前版本的Cypher在通过它们传递值时是否已处理MATCH链接?

1 个答案:

答案 0 :(得分:7)

您在查询的前期提供的起点越准确,效率就越高。

你的第一场比赛不太准确,实际上它会使用遍历匹配器来匹配所有可能的关系。

采用以下neo4j控制台示例:http://console.neo4j.org/r/jsx71g

您的第一个查询在示例中将如下所示:

MATCH (n:User { login: 'nash99' })-[:KNOWS]->(friend)
RETURN count(*)

您可以在前面看到dbhits的数量:

    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)-[: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 hits:

的问题上,上述查询与以下内容之间没有区别
MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)
WITH friend
MATCH (friend)-[:BUYS)->(c:Car)
RETURN (friend)

我建议您使用neo4j控制台查看显示上述信息的结果详细信息。

如果您需要快速对图形进行原型设计以进行测试,您可以使用Graphgen,在cypher语句中导出图形并在neo4j控制台中加载这些语句。

以下是我用于控制台http://graphgen.neoxygen.io/?graph=29l9XJ0HxJ2pyQ

的graphgen生成的链接

克里斯