密码:如何在可能为空的集合中使用UNWIND

14

有没有办法使用UNWIND处理可能为空的集合(例如OPTIONAL UNWIND g)?

例如,在附加的查询中,有时会发现集合(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
UNWIND items as i
  OPTIONAL MATCH(i) --(ig: FunctionalArea)
RETURN length(groups), length(users), length(items), length(locations), count(distinct ig)

我找到了一个解决方法,但并不是很满意。当我向项目集合中插入一个虚拟节点时,我可以每次展开它而不会失去结果。

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)

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

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

谢谢!


1
我曾经也遇到过同样的困境。我也采用了dummy节点根,虽然不太优雅,但似乎确实很有效。我很想听听其他可能的解决方案,特别是更优雅的方案。 - Dave Bennett
3个回答

21
你可以使用:

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

(注:该语句为一段代码,无法直接翻译。)

3
甚至可以使用新功能unwind coalesce(items, [null]) as item - tscherg
1
unwind coalesce(items, [null]) as item will work only when items is explicitly null. If items is an empty collection then this approach won't work. Better solution is as mentioned i.e. UNWIND (CASE items WHEN [] then [null] else items end) as item - AbhishekTripathi
我尝试了这个,但是它返回以下错误。 未知函数'UNWIND'(第2行,第8列(偏移量:21)) “RETURN UNWIND(CASE f WHEN [] then [null] else f end)as items” - Zohaib

2
我建议您,不要使用太多的“unwind”,而是尝试重新组织您的查询语句。这是一个快速重构的示例,仅供参考;请查看以下内容:
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)

子组将收集独立的根组,因为 *0...。所以第一个可选匹配不再必要。
我尽早进行了计数。仅需要在第二层级别上的用户来收集项目数据。享受 :)

0

@Michael Hunger的回答对我有用。但是,当列表本身为null时,我遇到了问题。所以,我找到了一个解决办法,可以处理nullempty列表,就像这样:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接