将多个标签与Cypher匹配时,结果不正确

时间:2014-08-20 23:52:48

标签: neo4j cypher

我有一个图表,其中包含表示权限层次结构中的角色的节点。权限层次结构如下所示:

(:role:owners)-[:CONTACT]->(:role:admins)-[:CONTACT]->(:role:employees)
-[:CONTACT]->(:role:contacts)

然后将联系人附加到每个角色节点,如下所示:

(:contact {id: "1"})-[:CONTACT]->(:role:owners)
(:contact {id: "2"})-[:CONTACT]->(:role:employees)

我试图运行以下查询,如果用户是所有者或管理员(例如联系人1),则返回:contacts角色,如果用户是:employees角色,则返回MATCH (c:contact {id: "1"}) WITH c MATCH (g:role) WHERE (c)-[:CONTACT*1..2]->(:admins)-->(:employees)-->(g:contacts) OR (c)-[:CONTACT]->(g:employees) RETURN DISTINCT c, g 角色员工(如联系人2)。

c                          g
(:contact {id: "1"})       (:role:contacts)
Returned 1 row

预期结果

c                          g
(:contact {id: "1"})       (:role:owners)
(:contact {id: "1"})       (:role:admins)
(:contact {id: "1"})       (:role:employees)
(:contact {id: "1"})       (:role:contacts)
Returned 4 rows

实际结果

:role

我认为此查询只会返回包含:contacts标签和:employees:owners的节点,但它也会返回包含:admins和{{1}的节点}标签。

为什么要返回这些额外的节点,如何防止它这样做呢?这是针对Neo4j 2.1.2。

其他信息

我想我已经发现了这个错误。如果找不到有效路径,则看起来正在删除标签检查。在以下示例中,请注意(c1)(g:projectcontacts)之间没有路径,因为没有(:projectcontacts)个节点。在这种情况下,将删除projectcontacts匹配,并返回匹配(c1)-[:CONTACT*1..3]->(g:role)的所有节点。

这是在Neo4j 2.1.3服务器上:

neo4j-sh (?)$ CREATE
>   (o:role:owners {name:"Owners"})-[:CONTACT]->(:role:admins {name:"Admins"})-[:CONTACT]->
>   (e:role:employees {name:"Employees"})-[:CONTACT]->(:role:contacts {name:"Contacts"})
> CREATE
>   (c1:contact {id: "test1"})-[:CONTACT]->(o)
> CREATE
>   (c2:contact {id: "test2"})-[:CONTACT]->(e)
> 
> WITH c1
> 
> MATCH (g:role)
> WHERE
>   (c1)-[:CONTACT*1..2]->(:admins)-->(:employees)-->(g:contacts) OR
>   (c1)-[:CONTACT]->(g:employees) OR
>   (c1)-[:CONTACT*1..3]->(g:projectcontacts)
> RETURN DISTINCT c1, g;
+-------------------------------------------------------+
| c1                     | g                            |
+-------------------------------------------------------+
| Node[4439]{id:"test1"} | Node[4438]{name:"Contacts"}  |
| Node[4439]{id:"test1"} | Node[4436]{name:"Admins"}    |
| Node[4439]{id:"test1"} | Node[4437]{name:"Employees"} |
| Node[4439]{id:"test1"} | Node[4435]{name:"Owners"}    |
+-------------------------------------------------------+
4 rows
Nodes created: 6
Relationships created: 5
Properties set: 6
Labels added: 10
50 ms

如果我们从匹配查询中删除不存在的节点标签,我们会得到预期的结果。

neo4j-sh (?)$ CREATE
>   (o:role:owners {name:"Owners"})-[:CONTACT]->(:role:admins {name:"Admins"})-[:CONTACT]->
>   (e:role:employees {name:"Employees"})-[:CONTACT]->(:role:contacts {name:"Contacts"})
> CREATE
>   (c1:contact {id: "test1"})-[:CONTACT]->(o)
> CREATE
>   (c2:contact {id: "test2"})-[:CONTACT]->(e)
> 
> WITH c1
> 
> MATCH (g:role)
> WHERE
>   (c1)-[:CONTACT*1..2]->(:admins)-->(:employees)-->(g:contacts) OR
>   (c1)-[:CONTACT]->(g:employees)
> RETURN DISTINCT c1, g;
+------------------------------------------------------+
| c1                     | g                           |
+------------------------------------------------------+
| Node[4445]{id:"test1"} | Node[4444]{name:"Contacts"} |
+------------------------------------------------------+
1 row
Nodes created: 6
Relationships created: 5
Properties set: 6
Labels added: 10
55 ms

1 个答案:

答案 0 :(得分:0)

比尔,

我肯定不知道这一点,但我倾向于猜测问题是你通过在WHERE子句中为它添加标签来重新定义g。应用标签可能会导致g被视为要匹配的模式。

这是对还是错,这是一种方法来进行与问题无关的查询(现在纠正做你想做的事):

MATCH (c1:contact {id : 'test'})
WITH c1
MATCH (c1)-[:CONTACT]->(f:role)-[:CONTACT*1..]->(g:contacts)
WITH c1, CASE WHEN 'employees' IN labels(f) THEN f ELSE g END AS h
RETURN DISTINCT c1, h

恩典与和平,

吉姆