Neo4j:根据财产

时间:2016-08-01 20:36:01

标签: graph neo4j nodes relationship with-statement

我在neo4j中有一个看起来像this的图表。我想把它变成类似this的东西。

广义问题:

您如何以特定顺序(例如按日期排序)遍历儿童并按照给定顺序在儿童之间建立关系?

具体问题:

每个(:Person)可能有多个(:Diagnosis)节点,多个(:Diagnosis)节点可以共享相同的(:Concept)。节点标记为"条件"是(:概念)节点。 (:诊断)节点表示人员诊断的发生,因此没有两个人共享(:诊断)节点。然而,可以诊断多个人具有相同类型的诊断,并且(:概念)节点描述诊断的类型(例如,II型糖尿病,动脉瘤等)。

我想基于(:Diagnosis)节点的时间顺序创建(:Concept)节点之间的关系路径,我只想包括第一次诊断每个(:Concept)。

到目前为止,我已经在(:Person)和(:Concept)之间建立了新的关系:

(:Person {person_id: <some_number>})-[:DIAGNOSED_WITH {start_date: yyyy/mm/dd}]->(:Concept)

我一直用一个人(:人)测试一下。我使用以下cypher查询执行此操作:

match (p:Person {person_id: "12345"})--(c:ConditionOccurrence)--(con:Concept) WITH 
    p.person_id as people, con.concept_id as concepts, min(c.condition_start_date) as 
    start_date  ORDER BY  start_date, concepts
MATCH (p1:Person {person_id: people})
MATCH (c2:Concept {concept_id: concepts})
MERGE (p1)-[:DIAGNOSED_WITH {start_date: start_date}]->(c2)

现在我想根据[:​​DIAGNOSED_WITH]关系中的开始日期在(:Concept)节点之间创建关系。看起来应该是这样的:

(concept 1)-[:NEXT {person_id: #}]->(concept 2)-[:NEXT {person_id: #})]->(concept 3)...

我尝试在给定(:Person)的所有[:DIAGNOSED_WITH]关系的集合上使用UNWIND,但我不认为我完全理解UNWIND如何与{{1}一起使用}}

以下查询似乎只是在同一开始日期进行诊断的所有(:Concept)节点之间绘制关系:

WITH

我也试过了&#34;触摸&#34;我通过关系触摸并触摸我已经遇到过的关系的方法,但是由于我对match (p:Person {person_id: "12345"})-[d:DIAGNOSED_WITH]->(c:Concept) WITH p.person_id AS person_id, d AS diagnoses ORDER BY d.start_date WITH collect(diagnoses) as ordered_diagnoses, person_id as person_id UNWIND ordered_diagnoses as diagnosis MATCH (:Person {person_id: person_id})-[diagnosis]->(c1:Concept) MATCH (:Person {person_id: person_id})-[d2:DIAGNOSED_WITH]->(c2:Concept) WHERE d2.start_date >= diagnosis.start_date AND d2 <> diagnosis WITH min(d2.start_date) AS min_start_date2, diagnosis, person_id, c1 MATCH (:Person {person_id: person_id})-[:DIAGNOSED_WITH {start_date: min_start_date2}]->(c2:Concept) MERGE (c1)-[:NEXT {person_id: person_id, start_date1: diagnosis.start_date, start_date2: min_start_date2}]->(c2) UNWIND缺乏了解,该代码并没有按照我想要的方式工作:

WITH

请帮忙!谢谢!

2 个答案:

答案 0 :(得分:1)

我决定停止在cypher中进行攻击,并使用py2neo包在python中完成。更直截了当。如果您感兴趣,请参阅以下代码:

#!/usr/bin/env python

from py2neo import authenticate, Graph
from py2neo import Node, Relationship

authenticate("localhost:7474", "neo4j", "neo3j")
# default uri for local Neo4j instance
graphdb = Graph('http://localhost:7474/db/data')

def set_NEXT_rels(person_id):
    concepts = graphdb.run("MATCH (p:Person {person_id: \""+person_id+"\"})-[d:DIAGNOSED_WITH]->(c:Concept) RETURN c.concept_id, d.start_date ORDER BY d.start_date, c.concept_name").data()
    for i in range(0, len(concepts)-1):
        d = graphdb.run("MATCH (p:Person {person_id: \""+person_id+"\"})-[d1:DIAGNOSED_WITH {start_date: \""+concepts[i]['d.start_date']+"\"}]->(c1:Concept {concept_id: \""+concepts[i]['c.concept_id']+"\"})  MATCH (p:Person {person_id: \""+person_id+"\"})-[d2:DIAGNOSED_WITH {start_date: \""+concepts[i+1]['d.start_date']+"\"}]->(c2:Concept {concept_id: \""+concepts[i+1]['c.concept_id']+"\"}) MERGE (c1)-[:NEXT {person_id: \""+person_id+"\", start_date_d1: d1.start_date, start_date_d2: d2.start_date}]->(c2)").data()

def process_conditions_by_person():
    people = graphdb.run("MATCH (p:Person) RETURN p.person_id").data()
    for person in people:
        set_NEXT_rels(person['p.person_id'])

def main():
    process_conditions_by_person()

if __name__ == "__main__":
    main()

答案 1 :(得分:1)

http://www.example/includes/amazon-config.php有助于你解决这个问题。具体来说,在帮助程序部分,集合函数子部分下,有一个过程apoc.coll.pairs([list]),它将接受一个列表并输出一个子列表对列表。最后一对将是列表中与null配对的最后一个元素,因此如果我们的目标是连接节点,我们应该删除它。

以下是一个使用示例:

WITH [1, 2, 3, 4, 5] AS stuff
CALL apoc.coll.pairs(stuff) YIELD value
WITH value[0..size(value)-1] AS numbers
RETURN numbers

这将输出:[[1, 2], [2, 3], [3, 4], [4, 5]]

因此,在使用它连接节点方面,您可以使查询搜索您感兴趣的节点,根据需要对它们进行排序,将它们收集()到列表中,调用pairs()APOC过程,然后使用FOREACH创建每对之间的关​​系。

修改

自我回答以来对APOC的一些更改:

1)apoc.coll.pairs()现在是一个函数,而不是一个过程(不需要使用CALL或YIELD,你可以使用它内联。

2)apoc.nodes.link()是一个过程,它接收节点集合并在它们之间创建给定类型的关系(因此您不必在foreach中自己创建关系)并且通常是首选方式链接你的节点。