Neo4j 使用Cypher匹配多个标签时的结果不正确

Neo4j 使用Cypher匹配多个标签时的结果不正确,neo4j,cypher,Neo4j,Cypher,我有一个图,其中的节点表示权限层次结构中的角色。权限层次结构如下所示: (:role:owners)-[:CONTACT]->(:role:admins)-[:CONTACT]->(:role:employees) -[:CONTACT]->(:role:contacts) (:contact {id: "1"})-[:CONTACT]->(:role:owners) (:contact {id: "2"})-[:CONTACT]->(:role:employee

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

(:role:owners)-[:CONTACT]->(:role:admins)-[:CONTACT]->(:role:employees)
-[:CONTACT]->(:role:contacts)
(:contact {id: "1"})-[:CONTACT]->(:role:owners)
(:contact {id: "2"})-[:CONTACT]->(:role:employees)
然后将联系人附加到每个角色节点,如下所示:

(: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
角色;如果用户是员工(如联系人2),则返回
:employees
角色

预期结果

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
标签的节点

它为什么返回这些额外的节点?我如何防止它这样做?这是针对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
比尔

我不确定这一点,但我倾向于猜测问题在于,通过在WHERE子句中向g添加标签,导致g被重新定义。应用标签可能导致g被视为要匹配的图案

无论这是对是错,这里有一种方法可以执行与问题不冲突的查询(现在已更正为执行您想要执行的操作):

恩典与和平


吉姆,你能给我们一些样品吗?你的意思是说你在
g
中得到的比预期的多,对吗?正确。它不仅返回
:role:contacts
节点,还返回中间
:role:owners
:role:admins
:role:employees
节点。我用结果更新了这个问题。在我看来这是一个bug,不知怎么的,这个模式也没有在标签上过滤。如果您添加了一个附加约束,例如
WHERE(g:contacts)或(g:employees)WITH g
,它是否解决了这个问题?是否有可能在控制台或其他地方获得一些示例数据?您能检查一下它是否与2.1.3相同吗?我已经更新了问题。我想我发现了这个bug,它仍然存在于2.1.3中。在我的例子中,g是一个需要匹配的模式。奇怪的是,只要标签在路径中,它就会按预期工作,一旦引入不在路径中的标签,它就会恢复为不正确的行为。当查询工作时,它不会返回我要查找的结果,很遗憾,MATCH(g:role)子句将g修复为特定的节点集合。在WHERE子句中使用带有不同标签的g可能会导致它被视为模式的未固定部分,而不是固定锚。Doh!我完全没有回答那个问题!我修改了答案中的查询,使其符合您的要求。