【问题标题】:failure trying to shorten CASE-based predicate尝试缩短基于 CASE 的谓词失败
【发布时间】:2017-11-27 16:43:27
【问题描述】:

这是受到这两个 SO 线程的启发:

Boolean value return from Neo4j cypher query without CASE

How to set property name and value on csv load?

我有一个包含 3 列的 CSV:

名字,prop_name,prop_value

约翰,体重,100

保罗,身高,200

约翰,头发颜色,金发

保罗,体重,120

所以,有很多人,他们的属性随机分布在不同的行中。我的目标是筛选行并将所有找到的属性分配给它们的持有者。为简单起见,我们只关注“权重”属性。

我确实知道如何使这项工作长期有效:

    LOAD CSV WITH HEADERS FROM
    "file:///test.csv" AS line
    WITH line
    MERGE (m:Person {name:line.first_name})
    WITH line, CASE line.prop_name WHEN "weight" THEN [1] ELSE [] END as loopW 
    UNWIND loopW as w
    MATCH (p:Person {name: line.first_name})
    SET p.weight = line.prop_value

然后,我尝试用更短的版本替换 CASE 行

    WITH line, collect(line.prop_name = "weight") as loopW 

...这导致了奇怪的行为,创建的节点确实分配了它们的“权重”键,但有时值错误。所以,我可以看到类似 (:Person {weight:blue})

什么是摆脱 CASE 的正确方法?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    您应该知道,您当前的使用会过滤掉所有没有“权重”作为 prop_name 的行(空集合的 UNWIND 会清除所有其他行,它们不会被处理)。

    您真正需要的是在节点上设置动态命名属性的更好方法,这样您就可以完全避免使用 CASE。

    如果您可以安装APOC Procedures(请阅读顶部说明如何修改neo4j.conf以将程序列入白名单,并注意版本矩阵以确保您获得与您的Neo4j版本对应的版本) 有一个非常适合您尝试做的事情:CALL apoc.create.setProperty( [node,id,ids,nodes], key, value) YIELD node

    用法类似于:

    LOAD CSV WITH HEADERS FROM
    "file:///test.csv" AS line
    MERGE (m:Person {name:line.first_name})
    CALL apoc.create.setProperty(m, line.prop_name, line.prop_value) YIELD node
    RETURN count(distinct m)
    

    编辑

    扩展原始查询的问题:

    UNWIND 以相对于集合中元素数量的乘法方式生成行。如果行中的集合有 5 个元素,则单行将产生 5 行,每个元素一个。如果集合为空,则将删除该行,因为集合中没有任何元素可以输出行。因此,查询中任何进一步的WITH line, CASE ... 行都不会有任何好处。

    让我们通过示例输入 csv 来分析原始查询:

    LOAD CSV WITH HEADERS FROM
    "file:///test.csv" AS line
    WITH line  //redundant, line not needed
    MERGE (m:Person {name:line.first_name}) // 4 rows corresponding with 2 nodes
    WITH line, CASE line.prop_name WHEN "weight" THEN [1] ELSE [] END as loopW 
    // still 4 rows, 2 have [1] as loopW, the other 2 have [] as loopW
    UNWIND loopW as w // 2 rows eliminated by unwinding empty collections
    MATCH (p:Person {name: line.first_name})
    SET p.weight = line.prop_value
    // only 2 rows are for 'John,weight,100' and 'Paul,weight,120'
    // any further repetitions of WITH line, CASE ... UNWIND for different props will fail and eliminate the remaining 2 rows.
    

    【讨论】:

    • Wrt 擦除其他行......我打算进一步添加“WITH line, CASE line.prop_name WHEN”块,除了“weight”之外还有其他属性你能扩展吗?那一点?
    • 另外,只是为了让我可以从错误中吸取教训 - 为什么特别是 collect() 语法在我的情况下没有解决?
    • 在我的回答中添加了更多解释。在您学习时,它有助于在查询中的各个点返回输出并查看每个连续行在做什么。此外,尝试 PROFILE 查询并观察查询执行时行数的增加和减少。
    • 对了,我刚刚安装了APOC。有点,因为我只能访问 apoc.load.* 和 apoc.coll.*,即使我在 conf 文件中已将 apoc.* 以及 .trigger 和 .meta 列入白名单且不受限制。我敢肯定,文件位置是正确的,因为在我进行更改之前,我根本无法访问 APOC。还仔细检查了版本——neo4j 和 jar 都是 3.3.0。对不起,如果这里是题外话。
    • 好的,修复了 apoc 问题;功能按描述工作。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多