使用Cypher从树中返回嵌套的分层JSON

时间:2015-12-11 23:43:00

标签: neo4j cypher

我目前正在使用console.neo4j.org上的示例数据编写一个输出分层JSON的查询。

使用

创建示例数据
create (Neo:Crew {name:'Neo'}), (Morpheus:Crew {name: 'Morpheus'}), (Trinity:Crew {name: 'Trinity'}), (Cypher:Crew:Matrix {name: 'Cypher'}), (Smith:Matrix {name: 'Agent Smith'}), (Architect:Matrix {name:'The Architect'}),
(Neo)-[:KNOWS]->(Morpheus), (Neo)-[:LOVES]->(Trinity), (Morpheus)-[:KNOWS]->(Trinity),
(Morpheus)-[:KNOWS]->(Cypher), (Cypher)-[:KNOWS]->(Smith), (Smith)-[:CODED_BY]->(Architect)

理想输出如下

name:"Neo"
children: [
  { 
    name: "Morpheus",
    children: [
      {name: "Trinity", children: []}
      {name: "Cypher", children: [
        {name: "Agent Smith", children: []}
      ]}
    ]
  }
]
}

现在,我正在使用以下查询

MATCH p =(:Crew { name: "Neo" })-[q:KNOWS*0..]-m
RETURN extract(n IN nodes(p)| n)

得到这个

[(0:Crew {name:"Neo"})]
[(0:Crew {name:"Neo"}), (1:Crew {name:"Morpheus"})]
[(0:Crew {name:"Neo"}), (1:Crew {name:"Morpheus"}), (2:Crew {name:"Trinity"})]
[(0:Crew {name:"Neo"}), (1:Crew {name:"Morpheus"}), (3:Crew:Matrix {name:"Cypher"})]
[(0:Crew {name:"Neo"}), (1:Crew {name:"Morpheus"}), (3:Crew:Matrix {name:"Cypher"}), (4:Matrix {name:"Agent Smith"})]

有任何提示可以解决这个问题吗?感谢

2 个答案:

答案 0 :(得分:8)

在neo4j 3.x中,在neo4j服务器上安装APOC plugin后,您可以调用apoc.convert.toTree程序生成类似的结果。

例如:

MATCH p=(n:Crew {name:'Neo'})-[:KNOWS*]->(m)
WITH COLLECT(p) AS ps
CALL apoc.convert.toTree(ps) yield value
RETURN value;

...将返回如下所示的结果行:

    {
      "_id": 127,
      "_type": "Crew",
      "name": "Neo",
      "knows": [
        {
          "_id": 128,
          "_type": "Crew",
          "name": "Morpheus",
          "knows": [
            {
              "_id": 129,
              "_type": "Crew",
              "name": "Trinity"
            },
            {
              "_id": 130,
              "_type": "Crew:Matrix",
              "name": "Cypher",
              "knows": [
                {
                  "_id": 131,
                  "_type": "Matrix",
                  "name": "Agent Smith"
                }
              ]
            }
          ]
        }
      ]
    }

答案 1 :(得分:2)

在这个重要主题上,这是一个非常有用的话题,我想在进一步探讨之后再添加一些想法。

首先,使用APOC“ toTree” proc有一些限制,或者更好的说是依赖项。架构的“树状”确实很重要。例如,上面的APOC调用中缺少LOVES关系,并且我理解为什么-使用“ toTree”时很难包含该关系-简单的添加有点像在层次结构中添加属性,而是作为关系。做起来不错,但混淆了简单的KNOWS树。要点是,一个很好的问题是“我如何应对此类挑战”。这个答复就是关于这个。

我确实建议您提高一些JSON技能,因为这将为您提供更精细的控制。就个人而言,我发现最初的探索有些痛苦。可能是因为我是XML的人:),但是一旦您弄清了所有的[,{和(),这实际上是有效地将最能描述为数据报告的强大方法。是很容易成为一类的东西,它提供了一种很好的方法将其推回应用程序。

相对于仅请求JSON,我发现perf对“ toTree”也是一个挑战。我在下面添加了一个非常简单的外观,以了解您的RETURN可能是什么样子。它遵循以下BN格式。我很乐意看到它的创建更加成熟,因为可能性千差万别,但这是我发现有用的东西,因此,我暂时将其发布。正如他们所说; “更多的潜水留给读者”?

我已经混淆了这些值,但这是一个实际的查询,我将它称为一个非常差的图形体系结构示例,在尝试访问有关其的整体报告时,其许多设计“错误”导致了一些严重的性能问题。图。如本例中所示,我继承的初始报告查询在服务器上花费了几分钟,并且无法在我的笔记本电脑上运行-使用此策略,更新的查询现在在大约200K db的我相当笨拙的笔记本电脑上运行大约5秒钟节点和.5M关系。我添加了“人”分组别名,以提醒每个数组元素中“人”将有所不同,但是父结构将一遍又一遍地重复。将其放在手工种植的树上的位置很重要,但是具有执行此功能的功能很强大。

底线是RETURN语句中对JSON的一种成熟用法,可让您强大地控制Cypher查询中的结果。

RETURN STATEMENT CONTENT:    
<cypher_alias> 
      {.<cypher_alias_attribute>,
        ...,
        <grouping_alias>:
          (<cypher_alias>
            {.<cypher_alias_attribute,
              ...
            }
          )
        ...
      }

MATCH (j:J{uuid:'abcdef'})-[:J_S]->(s:S)<-[:N_S]-(n:N)-[:N_I]->(i:I), (j)-[:J_A]->(a:P)
WHERE i.title IN ['title1', 'title2']
WITH a,j, s, i, collect(n.description) as desc
RETURN j{.title,persons:(a{.email,.name}), s_i_note:
 (s{.title, i_notes:(i{.title,desc})})}