Cypher:将UNWIND与可能为空的集合一起使用

时间:2015-04-24 07:03:39

标签: performance graph neo4j cypher

有没有办法将UNWIND用于潜在的空集合(例如OPTIONAL UNWIND g )?

例如,在附加查询中,有时候(第3个块)集合(项)是空的,但其他集合的结果仍然相关。

在这里,我想要查看子图的一些数字并返回各种节点类型(组,用户,位置,项目,项目组)的计数。 项目组只能通过项目派生。 并且因为有多个项目附加到多个用户,如果我直接在第二个块中包含项目组而没有首先聚合,则会非常慢。

MATCH(group: Group {id: "12345"})
OPTIONAL MATCH(group) - [: IS_PARENT * 0..] - > (subgroup: Group)

WITH collect(distinct subgroup) as groups
UNWIND groups as group
  OPTIONAL MATCH(u: User) - [: BELONGS_TO] - > (group)
  OPTIONAL MATCH(u) --(i: Item)
  OPTIONAL MATCH(u) --(l: Location)
WITH groups, collect(distinct u) as users, collect(distinct i) as items, collect(distinct l) as locations
UNWIND items as i
  OPTIONAL MATCH(i) --(ig: FunctionalArea)
RETURN length(groups), length(users), length(items), length(locations), count(distinct ig)

我找到了解决方法,但我对此并不满意。 当我将一个虚拟节点插入到items集合中时,我可以每次都放松它而不会丢失结果。

MATCH(group: Group {id: "12345"})
OPTIONAL MATCH(group) - [: IS_PARENT * 0..] - > (subgroup: Group)

WITH collect(distinct subgroup) as groups
UNWIND groups as group
  OPTIONAL MATCH(u: User) - [: BELONGS_TO] - > (group)
  OPTIONAL MATCH(u) --(i: Item)
  OPTIONAL MATCH(u) --(l: Location)
WITH groups, collect(distinct u) as users, collect(distinct i) as items, collect(distinct l) as locations

>> 
MATCH(ig:ItemGroup)
WITH groups, users, ([head(collect(ig))] + items) as items, locations
<<
UNWIND items as i
  OPTIONAL MATCH(i) --(ig: FunctionalArea)
RETURN length(groups), length(users), length(items), length(locations), count(distinct ig)

我正在考虑编写两个单独的查询,但这会导致复杂的客户端逻辑。

非常感谢任何想法和提示。

谢谢!

2 个答案:

答案 0 :(得分:10)

您可以使用:

UNWIND (CASE items WHEN [] then [null] else items end) as item

答案 1 :(得分:1)

我建议你,而不是使用这么多的放松,尝试重新组织你的查询。

它是一个快速重构的,但它只是一个建议;)检查它:

MATCH(group: Group {id: "12345"})-[:IS_PARENT*0..]->(subgroup: Group)
OPTIONAL MATCH(u: User)-[: BELONGS_TO]->(subgroup)
OPTIONAL MATCH(u) -- (l: Location)

WITH COLLECT(DISTINCT subgroup) AS g, COLLECT(DISTINCT u) AS uc,
    count(distinct subgroup) as groups, 
    count(distinct u) as users, 
    count(distinct l) as locations

UNWIND uc as u

OPTIONAL MATCH(u) --(i: Item)
OPTIONAL MATCH(i) --(ig: FunctionalArea)

RETURN groups, users, count(DISTINCT i) AS items, locations, count(distinct ig)

子组也将收集独立的根组,bc为* 0 ..因此,不再需要第一个可选匹配。

我尽可能早地计算了数。只有二​​级用户才需要收集项目数据。享受:)