在Cypher / Neo4j的MATCH子句中重复构造

时间:2013-11-30 22:39:44

标签: neo4j cypher modeling

背景: 一种系统,其中许多兴趣点(pois)在多个层次结构中彼此相关。 A可以是一个层次结构中的B的父级,而在另一个层次结构中,A可以是B的子级(或者甚至是另一个子级)。因此,Neo4j图包含层次结构和父子关系作为单独的节点,而不是将pois与[isChildOf]关系链接。

可以使用此cypher脚本生成用于说明此情况的图表。我正在使用Neo4j 2.0.0-M06。 我已经为可读性添加了一些标签,但我不想依赖它们进行查询。

create (_1 {`name`:"Class"})
create (_4:Class {`name`:"Poi"})
create (_5:Class {`name`:"PoiType"})
create (_9:Class {`name`:"Hierarchy"})
create (_10:Class  {`name`:"ParentChildRelation"})
create _4-[:`isA`]->_1
create _5-[:`isA`]->_1
create _9-[:`isA`]->_1
create _10-[:`isA`]->_1
create (_26:PoiType   {`poitypeid`:"2", `name`:"City"})
create (_27:PoiType   {`poitypeid`:"3", `name`:"Province "})
create (_28:PoiType  {`poitypeid`:"4", `name`:"Country"})
create (_29:Poi {`poiid`:"72882",`name`:"Netherlands"})
create (_30:Poi {`poiid`:"126",`name`:"Gelderland"})
create (_31:Poi {`poiid`:"52662",`name`:"Wageningen"})
create (_32:Poi {`poiid`:"8839",`name`:"Ede"})
create _26-[:`isA`]->_5
create _27-[:`isA`]->_5
create _28-[:`isA`]->_5
create _29-[:`isA`]->_4
create _30-[:`isA`]->_4
create _31-[:`isA`]->_4
create _32-[:`isA`]->_4
create _29-[:`isOfType`]->_28
create _30-[:`isOfType`]->_27
create _31-[:`isOfType`]->_26
create _32-[:`isOfType`]->_26
create (_33:Hierarchy {`treeid`:"1",`name`:"GeoAdmin"})
create _33-[:`isA`]->_9
create _33-[:`isOfType`]->_4
create (_34:ParentChildRelation {`pcrid`:"1"})
create _34-[:`isA`]->_10
create _34-[:`belongsTo`]->_33
create _34-[:`relationParent`]->_29
create _34-[:`relationChild`]->_30
create (_35:ParentChildRelation {`pcrid`:"2"})
create _35-[:`isA`]->_10
create _35-[:`belongsTo`]->_33
create _35-[:`relationParent`]->_30
create _35-[:`relationChild`]->_31
create (_36:ParentChildRelation {`pcrid`:"3"})
create _36-[:`isA`]->_10
create _36-[:`belongsTo`]->_33
create _36-[:`relationParent`]->_30
create _36-[:`relationChild`]->_32
create (_37:Hierarchy {`treeid`:"2",`name`:"SomePoiHierarchy"})
create _37-[:`isA`]->_9
create _37-[:`isOfType`]->_4
create (_38:ParentChildRelation {`pcrid`:"4"})
create _38-[:`isA`]->_10
create _38-[:`belongsTo`]->_37
create _38-[:`relationParent`]->_29
create _38-[:`relationChild`]->_32
;

要概述层次关系,像这样的查询工作正常:

MATCH ptp<-[r4:isOfType]-p<-[r1:relationParent]-pcr-[r2:relationChild]->c-[r5:isOfType]->ptc,pcr-[r3:belongsTo]->h 
RETURN ptp.name,p.name,ptc.name,c.name,h.name

导致:

ptp.name    p.name       ptc.name   c.name          h.name
Country     Netherlands  City       Ede             SomePoiHierarchy
Country     Netherlands  Province   Gelderland      GeoAdmin
Province    Gelderland   City       Ede             GeoAdmin
Province    Gelderland   City       Wageningen      GeoAdmin

如图所示,这是图表中退出的路径之一

Nederland <- [relationParent] – pcr(1) – [relationChild] -> Gelderland <- [relationParent] – pcr(2) – [relationChild] -> Wageningen

问题: 当我想在层次结构中的分支中获取给定类型的所有节点时,我有一个未定义的构造数量,如

<- [relationParent] – pcr – [relationChild] ->  

在路上。

当在节点之间使用直接[isChildOf]关系时,我会使用类似这样的东西

start n=node(84)  
match n<-[r1:IsChildOf*]-m-[r2:IsOfType]->pt
where pt.name="City"
return n,n.name,m,m.name,pt.name

但现在我需要一些语法,允许我重复整个构造,包括通过parentchildrelation节点的关系。

谁知道怎么做?

2 个答案:

答案 0 :(得分:1)

你能做什么:

首先你的关系类型中有一个拼写错误:“isOfType”以小写“i”开头。

这个结果返回了太多结果,因为它还包括ParentChildRelations

MATCH n-[r1:relationParent|relationChild*]-m-[r2:isOfType]->pt 
WHERE pt.name="City" 
RETURN n,n.name,m,m.name,pt.name

这就是为什么我将它限制在:Poi

MATCH n-[r1:relationParent|relationChild*]-m-[r2:isOfType]->pt 
WHERE pt.name="City" AND n:Poi 
RETURN n,n.name,m,m.name,pt.name

返回:

+------------------------------+
| n.name        | m.name       |
+------------------------------+
| "Ede"         | "Wageningen" |
| "Ede"         | "Ede"        |
| "Wageningen"  | "Ede"        |
| "Gelderland"  | "Wageningen" |
| "Gelderland"  | "Ede"        |
| "Netherlands" | "Wageningen" |
| "Netherlands" | "Ede"        |
+------------------------------+
7 rows

http://console.neo4j.org/r/5b1m96

答案 1 :(得分:1)

我没有看到Cypher中有一种方法可以指定一个由你的情况下所需的节点和关系组成的重复模式。所以我试图从不同的角度来考虑它。

我的理解是您在一对父节点和子节点之间引入了一个中间节点,并且该中间节点作为父子关系的层次结构类型的标识。因此,如果要查找某个层次结构的所有后代节点,可以从识别属于该层次结构的中间节点开始,然后查找这些中间节点的所有直接子节点。这可确保所有这些子节点必须位于所需的层次结构中。此外,中间节点必须与所需国家节点具有一个或多个关系。例如,如果要查找具有“GeoAdmin”层次结构的国家/地区节点的所有后代城市节点,可以按如下方式实现查询,

Match m-[:belongsTo]->h 
Where h.name ='GeoAdmin'
With m
Match cityType<-[:isOfType]-city<-[:relationChild]-m-[:relationParent|relationChild*1..6]-country-[:isOfType]->countryType
Where cityType.name ='City' and countryType.name ='Country'
Return distinct city

这将为您提供名为“Wageningen”和“Ede”的两个城市节点。 (我已经将模式的长度限制为6,你可以根据你的情况增加长度。)

如果要将层次结构更改为“SomePoiHierarchy”,则只需将第一个Where子句更改为“Where h.name ='SomePoiHierarchy'”,这应该只为您提供城市“Ede”。

我根据Michael Hunger的控制台在http://console.neo4j.org/?id=37qf3j创建了一个控制台。