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

Mik*_*378 4 neo4j cypher

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

MATCH (u1:User("123"))-[:KNOWS]-(friend)
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend
Run Code Online (Sandbox Code Playgroud)

在本文中,它是关于该WITH条款的:

那么它是怎样工作的?好吧,基本上只是一个流,尽管它可以是懒惰的(像返回一样懒惰),将结果传递给下一个查询.

所以我似乎应该像这样转换查询:

MATCH (u1:User("123"))-[:KNOWS]-(friend)
WITH friend
MATCH (friend)-[:BUYS]->(c:Car)
RETURN friend
Run Code Online (Sandbox Code Playgroud)

我是不是该?或者当前版本的Cypher是否已经MATCH通过它们传递值来处理链接?

Chr*_*sen 8

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

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

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

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

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

您可以在前面看到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
Run Code Online (Sandbox Code Playgroud)

如果您使用更准确的起点,那么当您从这一点开始时,您就是道路之王,请查看此示例查询并查看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
Run Code Online (Sandbox Code Playgroud)

所以为了终止你的查询,我会做这样的事情:

MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)-[:BUYS]->(c:Car)
RETURN friend
Run Code Online (Sandbox Code Playgroud)

您还可以指定朋友不能与用户相同:

MATCH (n:User { login: 'nash99' })
    WITH n
    MATCH (n)-[:KNOWS]->(friend)-[:BUYS]->(c:Car)
    WHERE NOT friend.id = n.id
    RETURN friend
Run Code Online (Sandbox Code Playgroud)

请注意,在db hits方面,上述查询与以下内容之间没有区别:

MATCH (n:User { login: 'nash99' })
WITH n
MATCH (n)-[:KNOWS]->(friend)
WITH friend
MATCH (friend)-[:BUYS)->(c:Car)
RETURN (friend)
Run Code Online (Sandbox Code Playgroud)

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

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

这是我用于控制台的graphgen代的链接http://graphgen.neoxygen.io/?graph=29l9XJ0HxJ2pyQ

克里斯

  • 不,你可以,你应该,问题是你没有定义一个特定的起点.如果你翻译你对Cypher说"嘿,我找到了与用户123连接的类型KNOWS的所有可能的关系",你最好说"Hey Cypher,用标签索引找到我的用户123,然后从这个用户找到KNWOS与我联系的所有关系. (4认同)
  • 它将明显改变我编写查询的方式;) (2认同)