neo4j CYPHER - 在ON MATCH SET上创建条件的新节点

时间:2018-06-17 04:04:20

标签: python neo4j cypher py2neo pubmed

要将XML数据导入neo4j数据库,我首先将XML解析为python字典,然后使用CYPHER查询:

WITH $pubmed_dict as pubmed_article
UNWIND pubmed_article as particle
...
FOREACH (author IN particle.MedlineCitation.Article.AuthorList.Author |
  MERGE (a:Author {last_name: COALESCE(author.LastName, 'LAST NAME MISSING!')})
  ON CREATE SET a.first_name = author.ForeName, a.affiliation = author.AffiliationInfo.Affiliation
  ON MATCH SET a.first_name = author.ForeName, a.affiliation = author.AffiliationInfo.Affiliation
  MERGE (p)<-[:WROTE]-(a)      
)

不幸的是,作者在数据库中没有唯一的ID,因此不同的作者可能具有相同的姓氏但不同的姓名缩写或附属关系。

...
                <Author ValidYN="Y">
                    <LastName>Smith</LastName>
                    <ForeName>A L</ForeName>
                    <Initials>AL</Initials>
                    <AffiliationInfo>
                        <Affiliation>University X</Affiliation>
                    </AffiliationInfo>
                </Author>
...
                <Author ValidYN="Y">
                    <LastName>Smith</LastName>
                    <ForeName>A L</ForeName>
                    <Initials>AL</Initials>
                    <AffiliationInfo>
                        <Affiliation>University BUMBABU</Affiliation>
                    </AffiliationInfo>
                </Author>

我的目的是在author.LastName上合并,但在ON MATCH上检查作者是否具有相同的ForeName或相同的Affiliation,如果不是,则创建一个新节点。

我如何使用CYPHER查询?

编辑1

节点密钥约束是解决方案,但它是企业版功能。寻找解决方法。

编辑2

这段代码几乎完美无缺:

WITH $pubmed_dict as pubmed_article
    UNWIND pubmed_article as particle
        MERGE (p:Publication {pmid: particle.MedlineCitation.PMID.text})
        ON CREATE SET p.title = COALESCE (particle.MedlineCitation.Article.Journal.Title, particle.MedlineCitation.Article.ArticleTitle)
        ON MATCH SET p.title = COALESCE (particle.MedlineCitation.Article.Journal.Title, particle.MedlineCitation.Article.ArticleTitle)

    FOREACH (author IN particle.MedlineCitation.Article.AuthorList.Author |
      MERGE (a:Author {last_name: COALESCE(author.LastName, 'LAST NAME MISSING!'), first_name: COALESCE(author.ForeName, 'FIRST NAME MISSING!')})
      MERGE (p)<-[:WROTE]-(a)      
    )

总结一下: 对于我想创建新作者的每个作者,IF LastName或ForeName或Affiliation是不同的。对于那些最后一个名字遗失的作者,我也需要新的节点!和第一个名字缺少!

是否有可能在没有关键节点约束的情况下实现此结果? (因为这是企业版功能......)

2 个答案:

答案 0 :(得分:1)

您可以使用约束,然后neo4j将为您检查唯一性。

来自documentation

  

创建节点密钥以确保具有特定标签的所有节点都具有一组已定义的属性,这些属性的组合值是唯一的,并且该集合中的所有属性都存在

CREATE CONSTRAINT ON (author:Author)  ASSERT (author.first_name, author.last_name, author.affiliation) IS NODE KEY

答案 1 :(得分:1)

作者确实在Neo4j中有一个唯一的ID,即节点ID。这可用于标识节点,然后设置属性。也许是这样的:

Match (a:Author{LastName:'xxx',ForeName:'yyy'}) 
with a, id(a) as ID
where ID > -1
match (b) where id(b)=ID set b.first_name = author.ForeName, b.affiliation = author.AffiliationInfo.Affiliation

节点的ID不一定稳定或可预测,因此您必须在使用它之前直接访问它。

因为您正在使用python代码,所以您可以使用全局查询来更好地下拉作者节点数据:

match (a:Author{LastName:'xxx',ForeName:'yyy'})  return a.LastName,a.ForeName,id(a) as ID

然后,您可以编写一个csv文件来批量上传所需的信息。 csv可能如下所示:

> "ID","ForeName","LastName","Affiliation" 
"26","David","Smith","Johns Hopkins" 
etc.

python代码可以过滤不需要处理的节点。

然后加载文件:

LOAD CVS with HEADER file:///'xxx.csv' as line 
match (a) where id(a)=toInteger(line.ID) 
set a.Affiliation=line.toString(line.Affiliation")