将独立查询与WITH组合使用

时间:2014-03-17 13:59:46

标签: neo4j cypher

我有两个独立的操作:

MATCH ()<-[r:waitsFor]-() 
  SET r.active = true 

MATCH (start:Job) WHERE has(start.startedAt) OR has(start.completedAt)
  OPTIONAL MATCH (prev:Job)<-[r:waitsFor]-(start:Job) 
SET r.active = false 

它们在大约5s内执行4k节点和2k关系。 但是,如果使用 WITH

立即执行此操作
MATCH ()<-[r:waitsFor]-() 
  SET r.active = true 
WITH null AS none
MATCH (start:Job) WHERE has(start.startedAt) OR has(start.completedAt)
  OPTIONAL MATCH (prev:Job)<-[r:waitsFor]-(start:Job) 
SET r.active = false 

查询不会在合理的时间内执行。 我读过 WITH 文档。关于导致此类行为的 WITH ,我怎么理解?

2 个答案:

答案 0 :(得分:1)

不要那样做。正如您所说,它们是单独的查询,因此请单独运行它们。现在运行它们的方式是,对第一个中的每个匹配结果执行第二个查询。我正在使用的一个微小的本体图中的示例,其中146个节点标记为:OwlClass。考虑以下两个查询

- 查询1 -

MATCH (c:OwlClass) 
RETURN COUNT(*)

结果:

COUNT(*)
146
Returned 1 row in 102 ms

执行计划:

==> ColumnFilter(symKeys=["  INTERNAL_AGGREGATE01b2d10b-7bf4-43b4-a67d-fbe826c7a4dd"], returnItemNames=["COUNT(*)"], _rows=1, _db_hits=0)
==> EagerAggregation(keys=[], aggregates=["(  INTERNAL_AGGREGATE01b2d10b-7bf4-43b4-a67d-fbe826c7a4dd,CountStar())"], _rows=1, _db_hits=0)
==>   NodeByLabel(label="OwlClass", identifier="c", _rows=146, _db_hits=0)

- 查询2 -

MATCH (c:OwlClass) 
WITH null as n 
MATCH (d:OwlClass) 
RETURN COUNT(*)

结果:

COUNT(*)
21316
Returned 1 row in 734 ms

执行计划:

==> ColumnFilter(symKeys=["  INTERNAL_AGGREGATEe33d15c7-e357-4e32-9f7f-3fbc00dd58f6"], returnItemNames=["COUNT(*)"], _rows=1, _db_hits=0)
==> EagerAggregation(keys=[], aggregates=["(  INTERNAL_AGGREGATEe33d15c7-e357-4e32-9f7f-3fbc00dd58f6,CountStar())"], _rows=1, _db_hits=0)
==>   NodeByLabel(label="OwlClass", identifier="d", _rows=21316, _db_hits=0)
==>     ColumnFilter(symKeys=["c", "n"], returnItemNames=["n"], _rows=146, _db_hits=0)
==>       Extract(symKeys=["c"], exprKeys=["n"], _rows=146, _db_hits=0)
==>         NodeByLabel(label="OwlClass", identifier="c", _rows=146, _db_hits=0)

- 查询3 -

MATCH (c:OwlClass)
WITH COUNT(c) as count_c
MATCH (d:OwlClass)
RETURN count_c, COUNT(d) as count_d

结果:

count_c   count_d
146       146
Returned 1 row in 153 ms

执行计划:

==> ColumnFilter(symKeys=["count_c", "  INTERNAL_AGGREGATE17be6af7-abbb-4ef7-8250-ff050d6ba7c6"], returnItemNames=["count_c", "count_d"], _rows=1, _db_hits=0)
==> EagerAggregation(keys=["count_c"], aggregates=["(  INTERNAL_AGGREGATE17be6af7-abbb-4ef7-8250-ff050d6ba7c6,Count(d))"], _rows=1, _db_hits=0)
==>   NodeByLabel(label="OwlClass", identifier="d", _rows=146, _db_hits=0)
==>     ColumnFilter(symKeys=["  INTERNAL_AGGREGATE67abdc54-9c44-4353-bf82-e4aff895141e"], returnItemNames=["count_c"], _rows=1, _db_hits=0)
==>       EagerAggregation(keys=[], aggregates=["(  INTERNAL_AGGREGATE67abdc54-9c44-4353-bf82-e4aff895141e,Count(c))"], _rows=1, _db_hits=0)
==>         NodeByLabel(label="OwlClass", identifier="c", _rows=146, _db_hits=0)

-

从下往上阅读执行计划。在这种情况下,相关部分是行数如何变化。比较查询2和3的粗略解释。

查询2

  1. 首先获取标签为OwlClass的所有节点。现在有146种匹配模式。
  2. 通过将n设置为null来继续每个模式。
  3. 通过获取标签为OwlClass的所有节点来继续每个模式。现在有146 * 146 = 21316匹配模式。
  4. 通过计算汇总这些。现在有一种模式(计数)。把它返还。
  5. 查询3

    1. 首先获取标签为OwlClass的所有节点。现在有146种匹配模式。
    2. 通过计算汇总这些。现在有一种模式(计数)。
    3. 通过获取标签为OwlClass的所有节点来继续每个模式。现在有146种匹配模式。
    4. 通过计算汇总这些。现在有一种模式(计数)。归还。

答案 1 :(得分:0)

WITH子句用于将返回的信息“转发”到查询的另一部分。使用WITH null作为none并向前移动以执行后续匹配很容易在Neo4j中创建笛卡尔积。根据节点数量的不同,笛卡尔产品爆炸可能会非常庞大​​,需要花费大量时间才能完成。

因此,如果第二个查询中第一个查询中的'r'需要缩小匹配范围,则应使用WITH r。因为似乎不是这种情况(因为你使用WITH null作为无),这可能不是解决方案。

在我看来,你的情况是按顺序执行两个单独的查询。您应该查看UNION子句。它用于连接两个查询并合并其结果。您拥有的选项是普通的UNIONUNION ALL(删除重复项)。