【问题标题】:Cypher Query to Return Nodes in Path Order密码查询以路径顺序返回节点
【发布时间】:2015-01-19 20:16:21
【问题描述】:

我有一个 neo4j graphdb 存储节点的有序集合(比如说 Person 节点),每个人都有一个 Talent 节点:

(p:Person)-[:HAS_TALENT]->(t:Talent)

我正在组织一场才艺表演,并且有人们表演顺序的时间表:

(p:Person)-[:FOLLOWS*]->(q:Person)

我可以编写一个查询来返回一个路径,该路径表示人们执行的顺序,当我返回该路径时,Person 节点会按照它们在路径中出现的顺序显示。但是,当我执行子查询以返回人们正在执行的才能时,它们不再按路径排序。

有没有办法根据节点在路径中出现的顺序对节点进行排序?我尝试使用COLLECT 来获取 Person 节点列表,但我似乎无法找到一种方法来使用该集合来获取 Talent 节点的有序列表。

我当前的路径查询看起来像这样,有一个特殊的开始和结束节点,所以我知道谁是第一个和最后一个。 (我现在没有数据库在我面前,如果它不是正确的,请道歉):

MATCH p=(s:StartNode {side:"start"})-[:FOLLOWS*1..10]->(s:StartNode {side:"end"}) RETURN p

我已经通过了很多不同的选项来检索从头到尾的路径,它们各有利弊,但我找不到以相同顺序检索人才节点的方法。


编辑:看来我可能过度简化了我的示例场景。我实际使用的数据库有多个从开始到结束通过 Person 节点的路径,并且我有一个查询,首先选择从开始到结束的单个路径,然后再继续匹配 Talent 节点。向@Dirk Horsten 道歉,他回答了我提出的问题,但没有回答我需要回答的问题。

由于我已经在编辑此内容,@Dave Bennett 的回答解决了我的问题,因为 unwind 函数似乎为未来的 MATCH 子句保持路径顺序不变。

【问题讨论】:

  • 请包含您正在使用的查询
  • @FrobberOfBits 我已经对其进行了编辑以添加查询。我什至不一定附加到那个特定的查询(我已经尝试了几个,它们似乎都在不同程度上起作用),我只是无法想出一个查询来以路径顺序返回 Talent 节点.

标签: neo4j cypher


【解决方案1】:

假设表演者是人 1..5,他们每个人都拥有一个才能 A..E,因此Person 1Talent APerson 5Talent E。才艺表演从第 1 个人开始,到第 5 个人结束。

//match all of the possible show paths where the show starts
// with the first performer 
MATCH show=(:Person {name:'Person 1'})<-[:FOLLOWS*]-(:Person) 

// pass on the performers and the number of performers
// as identifiers with the WITH clause
WITH nodes(show) AS performers, length(show) AS num

// order the possible shows in descending order by number of performers
ORDER BY num DESC

// limit the list to the show with the most performances
LIMIT 1

// unwind the performers collection as individual performer
UNWIND performers AS p

// match the talent that matches the performers
MATCH p-[:HAS_TALENT]->(t:Talent)

// return the name of the performer and their talent
RETURN p.name, t.name

【讨论】:

  • 非常感谢!他们在这里的关键,似乎是unwind 函数,它似乎保持节点有序,这样当我匹配 p-->t 时,t 最终是有序的。现在完美运行!
【解决方案2】:

如果我在前面添加一个(显示)节点

create (s:show{date:'2014-01-31'})
create  (s)<-[:STARTS]-(p1:person{pId:1})-[:HAS_TALENT]->(:talent{tId:1})
create (p1)<-[:FOLLOWS]-(p2:person{pId:2})-[:HAS_TALENT]->(:talent{tId:2})
create (p2)<-[:FOLLOWS]-(p3:person{pId:3})-[:HAS_TALENT]->(:talent{tId:3})
create (p3)<-[:FOLLOWS]-(p4:person{pId:4})-[:HAS_TALENT]->(:talent{tId:4})
create (p4)<-[:FOLLOWS]-(p5:person{pId:5})-[:HAS_TALENT]->(:talent{tId:5})

那么这应该可以完成工作:

match spt=(s:show{date:'2014-01-31'})<-[:STARTS|FOLLOWS *]-(p:person)-[:HAS_TALENT]->(t:talent) 
return p.id as performer,t.tId as act order by length(spt)

当然你也可以返回完整的t,你可以collect(t.tId)或者任何你喜欢的 (在装有 Neo4j 的 PC 上测试)

【讨论】:

  • 这是一个很好的答案,但依赖于返回多个路径来确定 Talent 节点的顺序。在我正在使用的实际场景中,数据库有点复杂,并且从头到尾存在多个路径。因此,在获得 Talents 之前,我必须将事情缩小到单个 Person 节点路径。不过,这是我过度简化事情的错;您的回答与我提出的问题相符。
  • 谢谢,萨米。事实上,我首先非常接近戴夫的答案,但忘记了我仍然可以在放松后添加匹配项。所以我给了他一个赞成票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多