Cypher:通过结尾

时间:2017-03-02 12:10:23

标签: neo4j cypher

我有一个图表,包含表示版本路径中连接在一起的文档版本的节点。这些路径可以通过另一种类型的关系连接,这些关系表示文档版本化方式的变化。图的问题之一是用于创建它的源不是真正干净的,这就是为什么我试图编写一个查询来添加关系以在图中有一个干净的版本路径。

我坚持的部分如下: 假设我有两个不同版本控制期的节点路径。这些路径通过一种或多种关系连接在一起,从第二种类型指示文档的端口到新系统。我想要一个查询,它将使最后一个满足旧路径中的某些条件并将其连接到第一个满足新路径中的某些其他条件。

例如,在下图中,我想将(D)(2)联系起来,因为(1)不符合我的条件:

(A)-[:Version]->(B)-[:Version]->(C)-[:Version]->(D)
                 |               |
               Ported          Ported
                 |               |
(1)-[:Version]->(2)-[:Version]->(3)

我提出了不同的查询,但在某些情况下所有查询都失败了:

这个失败是因为有时旧文档被移植并拆分成多个文档,这意味着不同的路径,但我的查询只为一个'旧'一个选择一个新的'新'节点,从而忽略了一些路径。

//match all the 'port' and 'ported' relations between old and new versioning system
match (new:Document)-[r:Link]-(old:Document) 
   where new.num =~'[A-Z].{4}-.*' and old.num =~'[A-Z].{3}-.*' and r.type in ['PORT','PORTED'] 
//find youngest one satisfying a condition, here a date
optional match(new)<-[:Version*]-(newAncestor:ArticleCode) 
   where newAncestor.dateBegin >= '2012-01-01'
with old, collect(new) + collect(newAncestor) as potentialNewVersions
unwind potentialNewVersions as potentialNew
with distinct old, potentialNew 
order by potentialNew.dateBegin , potentialNew.dateEnd 
with distinct old, collect(potentialNew)[0] as youngestNew

//find oldest one satisfying a condition
optional match(old) -[:Version *]->(oldChild:ArticleCode) 
   where oldChild.dateEnd <= youngestNew.dateBegin
with old, youngestNew, collect(old) + collect(oldChild) as potentialOldVersions
unwind potentialOldVersions as potentialOld
with distinct old, youngestNew, potentialOld 
order by potentialOld.dateEnd desc, potentialOld.dateBegin desc
   with distinct youngestNew, collect(potentialOld)[0] as oldestOld

merge(youngestNew)<-[:VersionGlobal]-(oldestOld)

第二个更简单,但为“新”节点选择了太多节点,因为多个版本可以满足日期条件。此外,如果旧路径和新路径之间的唯一“移植”关系位于限制日期之前的节点上,则可能会失败。

//this time I match all path of new versions whose first node satisfy condition
match p=(new:Document)-[:Version*0..]->(:Document)-[r:Link]-(old:ArticleCode) 
   where new.num =~'[A-Z].{4}-.*' and old.num =~'[A-Z].{3}-.*' and r.type in ['PORT','PORTED'] and new.dateBegin >= '2012-01-01' 
//take first node of each path
with distinct nodes(p)[0] as youngestNew, old
//find latest old node
optional match p=(old)-[:Version*0..]->(oldChild:ArticleCode) 
   where oldChild.dateFin <= youngestNew.dateDebut
with distinct last(nodes(p)) as oldestOld, old
merge(youngestNew)<-[:VersionGlobal]-(oldestOld)

由于

1 个答案:

答案 0 :(得分:0)

我认为我们找到了使用可选匹配和案例的答案:

match (new:Document)-[:Version*0..]-(:Document)-[r:Lien]-(:Document)-[:Version*0..]-(old:Document)
where *myConditions*

optional match (newAncestor:Document)-[:Version]->(new)
with distinct
case  
    when newAncestor.dateBegin < '2012-01-01' or newAncestor is null
    then new
end as youngestNew, old
where not(youngestNew is null)

optional match (old)-[:Version]->(oldChild:Document)
with distinct
youngestNew,
case 
    when oldChild.dateBegin > youngestNew.dateBegin or oldChild is null
    then old
end as oldestOld
where not(oldestOld is null)

*merge part*