我们有一个Neo4j图表,可以跟踪人们走过门的情况。它包含Person节点,Door节点和WALKED_THROUGH边。 person和door节点具有“name”属性,并且边缘具有“action”属性,该属性设置为“Entered”或“Exited”。
我需要回答的问题是:给定一个人,她至少进入一次,但从未退出的门的名称是什么?
我可以轻松获得相关路径:
match( (person:Person{name:'Mary'})-[walkedThroughEdges:WALKED_THROUGH]->(doors:Door) )
return person, walkedThroughEdges, doors
order by doors.Name
...产生这个:
╒═══════════════╤════════════════════╤═════════════════╕
│"person" │"walkedThroughEdges"│"doors" │
╞═══════════════╪════════════════════╪═════════════════╡
│{"name":"Mary"}│{"action":"Exited"} │{"name":"Door B"}│
├───────────────┼────────────────────┼─────────────────┤
│{"name":"Mary"}│{"action":"Entered"}│{"name":"Door B"}│
├───────────────┼────────────────────┼─────────────────┤
│{"name":"Mary"}│{"action":"Entered"}│{"name":"Door A"}│
├───────────────┼────────────────────┼─────────────────┤
│{"name":"Mary"}│{"action":"Entered"}│{"name":"Door A"}│
└───────────────┴────────────────────┴─────────────────┘
...但我无法弄清楚如何操纵结果以获得我需要的答案。在这种情况下,预期的答案是“门A”,因为玛丽进入门A至少一次,但从未退出。门B应该被排除在外,因为玛丽从那扇门出来了。
任何帮助都将不胜感激。
答案 0 :(得分:1)
编辑:如果您只需要用户刚进入的门,这应该可以。
match(person:Person{name:'Mary'})-[walkedThroughEdges:WALKED_THROUGH]->(door:Door)
with person, door, collect(walkedThroughEdges.action) as actions
with person, door, size(filter(action in actions where action = "Entered")) as enteredCount, size(actions) as total
where enteredCount = total
return person, door
order by door.Name
答案 1 :(得分:1)
此查询应该找到一个人曾经用过的门,但从来没有退出。 它类似于@InverseFalcon的方法,但使用不同的语法。
MATCH (person:Person{name:'John'})-[r:WALKED_THROUGH]->(door:Door)
WITH person, door, r.action AS action, COUNT(*) AS ct
WITH person, door, COLLECT({action: action, ct: ct}) AS x
WHERE SIZE(x) = 1 AND x[0].action = 'Entered'
RETURN person, door, x[0].ct AS num_enters
ORDER BY door.Name;
第一个WITH
子句使用aggregation来计算每个人每个门action
执行次数的次数。
第二个WITH
子句使用聚合来收集动作/计数对。 可以有1对或2对,因为有2种可能的操作。
WHERE
子句检查集合是否只有一个操作/计数对,并且操作是“已输入”。如果确实如此,则输入相关门但从未退出。
答案 2 :(得分:0)
我觉得这样的事情可以奏效......
您只能匹配“已输入”操作的WALKED_THROUGH
边缘。然后选择性地匹配那些存在Exited
边缘的人,门对。然后返回Exited
匹配项不存在的人员,门组合。
MATCH (person:Person {name:'Mary'})-[:WALKED_THROUGH {action: 'Entered'}]->(door:Door)
WITH person, door
OPTIONAL MATCH (person)-[exited:WALKED_THROUGH {action: 'Exited'}]->(door)
WITH person, door, exited
WHERE exited IS NULL
RETURN person, door
另一种方法是将它们全部匹配。然后只返回已进入且没有退出的那些。这可能更有意义,因为我认为一个人在考虑退出之前必须进入。
MATCH (person:Person {name:'Mary'})-[walked_through:WALKED_THROUGH]->(door:Door)
WITH person, door, collect(walked_through.action) AS walked_through
WHERE ALL(action IN walked_through WHERE action = 'Entered' )
RETURN person, door
然而,还有一种方法不是使用NOT EXISTS
。最明显的三种可能性。
MATCH (person:Person {name:'Mary'})-[walked_through:WALKED_THROUGH]->(door:Door)
WHERE NOT EXISTS((person)-[:WALKED_THROUGH {action: 'Exited'}]->(door))
RETURN person, door