【问题标题】:Cypher to get "unique longest simple (acyclic)" paths from given source nodeCypher 从给定的源节点获取“唯一最长的简单(非循环)”路径
【发布时间】:2017-06-29 12:10:30
【问题描述】:

我有这个简单的图表:

create (a:ent {id:'a'})-[:rel]->(:ent {id:'b'})-[:rel]->(c:ent {id:'c'})-[:rel]->(d:ent {id:'d'})-[:rel]->(:ent {id:'e'})-[:rel]->(a),
   (d)-[:rel]->(c),
   (c)-[:rel]->(f:ent {id:'f'})-[:rel]->(g:ent {id:'g'})-[:rel]->(a),
   (g)-[:rel]->(f)

看起来像这样:

鉴于是'a',即节点(:ent {id:'a'}),我想编写返回“恰好两个唯一最长的”路径的查询:

a->b->c->d->e
a->b->c->f->g

正如您在此处看到的,我应该在这里考虑图表中的周期。看来查询建议here应该没问题,我改写如下:

MATCH path=(:ent{id:'a'})-[:rel*]->(:ent)
WHERE ALL(n in nodes(path)
      WHERE 1=size(filter(m in nodes(path)WHERE m.id=n.id))
     )
RETURN path

我知道查询没有给出我想要得到的确切结果,但是如果我正确理解逻辑,它至少可以避免循环路径。我觉得这个查询可以是一个很好的起点。但这给了我奇怪的错误:

key not found:   UNNAMED26

这里有什么问题?我无法通过这个不清楚的错误描述来查明密码中的错误。

更新

我尝试了一个新的更简单的查询:

MATCH path=(s:ent{id:'a'})-[:rel*]->(d:ent)
WHERE not (d)-[:rel]->() OR (d)-[:rel]->(s)
RETURN extract(x IN nodes(path)| x.id) as result

返回:

╒═════════════════════╕
│result               │
╞═════════════════════╡
│[a, b, c, d, e]      │
├─────────────────────┤
│[a, b, c, d, c, f, g]│
├─────────────────────┤
│[a, b, c, f, g]      │
└─────────────────────┘

如您所见,由于循环(d)<->(c) 循环,它有一个冗余路径[a, b, c, d, c, f, g]。老实说,我觉得这篇文章中的原始/第一个查询应该消除它。谁能告诉我如何使它工作...?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    您可以使用apoc.path.expandConfig 查找路径,然后过滤掉最短的路径,只留下最长的路径。

    // start with the a node
    MATCH (a:ent {id :"a"})
    
    // use expandConfig with the relationship type and direction
    // use uniqueness of NODE_PATH to ensure that you don't backtrack
    // optionally include a minlevel, maxlevel
    CALL apoc.path.expandConfig(a, 
    {
      relationshipFilter: 'rel>',
      uniqueness: 'NODE_PATH',
      minLevel: 2,
      maxLevel: 10
    } ) yield path
    
    // collect the paths and the get the max length
    WITH COLLECT(path) AS paths, MAX(length(path)) AS longest_length
    
    // remove any of the paths that are not the max length
    WITH FILTER(path IN paths WHERE length(path)= longest_length) AS longest_paths
    
    // return each path matching the max length
    UNWIND longest_paths AS path
    RETURN path
    

    更新:基于 OP 的说明的替代答案。

    // alternate set of test data based on OP's comments
    MERGE (a:ent {id:'a'})-[:rel]->(b:ent {id:'b'})-[:rel]->(c:ent {id:'c'})
    MERGE (b)-[:rel]->(d:ent {id:'d'})
    MERGE (b)-[:rel]->(e:ent {id:'e'})-[:rel]->(f:ent {id:'f'})
    RETURN *
    

    以及更新后的查询

    // start with the a node
    MATCH (a:ent {id :"a"})
    
    // use expandConfig with the relationship type and direction
    // use uniqueness of NODE_PATH to ensure that you don't backtrack
    // optionally include a minlevel, maxlevel
    CALL apoc.path.expandConfig(a, 
    {
      relationshipFilter: 'rel>',
      uniqueness: 'NODE_PATH',
      minLevel: 1,
      maxLevel: 10
    } ) yield path
    
    // create two collections: one of nodes of full paths and the other nodes of paths shorted by one
    WITH COLLECT(path) AS paths,
         COLLECT(DISTINCT nodes(path)[0..size(nodes(path))-1]) AS all_but_last_nodes_of_paths
    
    // filter out the nodes of paths that match nodes in the shorted list
    // i.e. the paths that are already included in another list
    WITH [p IN paths WHERE NOT nodes(p) IN all_but_last_nodes_of_paths] AS paths_to_keep
    
    // return each path
    UNWIND paths_to_keep AS path
    RETURN path
    

    【讨论】:

    • 获取There is no procedure with the name apoc.path.expandConfig`为此数据库实例注册。请确保您正确拼写了程序名称并且程序已正确部署。我在 Neo4j CE 3.0.4 上。这个程序是在最近的版本中添加的吗?
    • 它用于确保不重新访问同一个节点,但它意外返回了两个所需的路径,因为我上面给出的图表正好包含两个等于最大长度为 5 的路径。这可能是因为对“最长”术语的误解。如果图形有路径a->b,a->b->c,a->b->da->b->e->f,那么上面的密码只返回a->b->e->f 路径,对吧?但是我想要a->b->c,a->b->d,a->b->e->f。所以在a->b,a->b->c中,它省略了a->b,因为它不是最长的,并且包含在a->b->c中,这是唯一最长的。很抱歉一开始不清楚“最长”。
    • 如果uniqueness 可以在apoc.path.subgraphNodes() 中配置,我觉得这应该是可行的。我对吗?目前无法获得上述评论中所述的输出吗?
    • np。所以为了确保我完全理解,如果图表是a->ba->b->ca->b->da->b->e->f。你不想要a->b->e,因为它已经包含在a->b->e->f 中——对吗?
    • np。我将其更改为返回路径。对此感到抱歉,这是我昨天忘记删除的迭代产物。是的,我认为路径练习对于编写密码查询至关重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 2011-06-30
    相关资源
    最近更新 更多