有没有一种方法可以使用apoc.load.json过程从JSON动态生成节点?

时间:2019-10-23 20:45:10

标签: neo4j

我想根据JSON文档创建一组节点和关系。这是示例JSON:

{"records": [{
    "type": "bundle",
    "id": "bundle--1",
    "objects": [
        {
            "type": "evaluation",
            "id": "evaluation--12345",
            "name": "Eval 1",
            "goals": [
                "test"
            ]
        },
        {
            "type": "subject",
            "id": "subject--67890",
            "name": "Eval 2",
            "goals": [
                "execute"
            ]
        },
        {
            "type": "relationship",
            "id": "relationship--45678",
            "relationship_type": "participated-in",
            "source_ref": "subject--67890",
            "target_ref": "evaluation--12345"
        }
    }]
}

我希望可以用Neo来表示JSON,类似于以下内容:

(:evaluation {properties})<-[:RELATIONSHIP]-(:subject {properties})

最终,我希望有一个模型,该模型表示通过几次密码调用生成的评估,主题和关系,并且外部操作尽可能少。是否可以使用apoc.create。*组调用从此JSON创建必要的节点和关系?我已尝试类似于以下内容来加载此JSON,并可以创建任意类型(在此情况下为“对象”)类型的节点。

WITH "file:///C:/path/to/my/sample.json" AS json
CALL apoc.load.json(json, "$.records") YIELD value
UNWIND value.objects as object
MERGE (o:object {id: object.id, type: object.type, name: object.name})
RETURN count(*)

我尝试更改JSONPath表达式以过滤不同的记录类型,但是由于嵌入了引号,因此很难运行像$.records..objects[?(@.type = 'subject')]这样的Goessner路径。这还会导致针对实际JSON多次运行(我有15种左右不同的类型),这可能非常耗时。 LoadJSON docs有一个简单的过滤器表达式,还有一个blog post显示了如何解析stackoverflow,但是JSON对象是通过易于映射在密码中的方式进行键控的。我应该知道有cypher trick或APOC可以帮助我解决此问题吗?

2 个答案:

答案 0 :(得分:0)

我将这种方法称为两遍方法:

第一遍:创建用于评估和主题的节点。如果有帮助,您可以使用apoc.do.case/when

第二遍:仅扫描关系,然后进行匹配以根据evaluationsubject查找source_reftarget_ref节点,然后合并或创建连接它们的关系。

像这样,您不会受到诸如连接节点之前的关系之类的情况的影响,也不会受到objects内有多少项的影响

答案 1 :(得分:0)

如Lju所指出的,apoc.do.case函数可用于创建一组要检查的条件,后跟一个cypher语句。将其与另一个apoc调用相结合,需要正确处理每个apoc调用的返回。我的答案最终看起来像这样:

WITH "file:///C:/path/to/my/sample.json" AS json
CALL apoc.load.json(json, "$.records") YIELD value as records
UNWIND records.objects as object
CALL apoc.do.case(
    [object.type="evaluation", "MERGE (:Evaluation {id: object.id}) ON CREATE SET Evaluation.id = object.id, Evaluation.prop1 = object.prop1",
    object.type="subject", "MERGE (:Subject {id: object.id}) ON CREATE SET Subject.id = object.id, Subject.prop1 = object.prop1",
    ....]
"<default case cypher query goes here>", {object:object}
)
YIELD value RETURN count(*)

请注意,有两个YIELD的apoc调用。使用别名可以帮助解析器区分对象。 apoc.do.case的{​​{3}}有点稀疏,但描述了该语句的语法。看起来还有其他方法可以完成此任务,但是使用较小的JSON文件,并且在少数情况下,效果很好。