微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

提取按关系排序的图路径中的节点

如何解决提取按关系排序的图路径中的节点

我的任务是找到一条路径并处理其中的节点,尊重它们在同一条路径中的顺序(因此顺序是由关系引起的)。

给定一个具有以下节点的图:

CREATE (a:temporary {name: 'm2'});
CREATE (a:temporary {name: 'f1'});
CREATE (a:temporary {name: 'b3'});
CREATE (a:temporary {name: 'd4'});

CREATE (a:temporary {name: 'p5'});
CREATE (a:temporary {name: 'p6'});
CREATE (a:temporary {name: 'p7'});

CREATE (a:temporary {name: 'k1'});
CREATE (a:temporary {name: 'k2'});

以及以下关系:

MATCH (a) WHERE a.name = 'b3' MATCH (b) where b.name = 'm2' CREATE (a)-[:KNowS {type: 'sibling'}]->(b);
MATCH (a) WHERE a.name = 'm2' MATCH (b) where b.name = 'f1' CREATE (a)-[:KNowS {type: 'friend'}]->(b);
MATCH (a) WHERE a.name = 'd4' MATCH (b) where b.name = 'b3' CREATE (a)-[:KNowS {type: 'coworker'}]->(b);

MATCH (a) WHERE a.name = 'p7' MATCH (b) where b.name = 'p6' CREATE (a)-[:KNowS {type: 'friend'}]->(b);
MATCH (a) WHERE a.name = 'p6' MATCH (b) where b.name = 'p5' CREATE (a)-[:KNowS {type: 'coworker'}]->(b);

MATCH (a) WHERE a.name = 'k1' MATCH (b) where b.name = 'b3' CREATE (a)-[:HAS]->(b);
MATCH (a) WHERE a.name = 'k1' MATCH (b) where b.name = 'd4' CREATE (a)-[:HAS]->(b);
MATCH (a) WHERE a.name = 'k1' MATCH (b) where b.name = 'm2' CREATE (a)-[:HAS]->(b);
MATCH (a) WHERE a.name = 'k1' MATCH (b) where b.name = 'f1' CREATE (a)-[:HAS]->(b);

MATCH (a) WHERE a.name = 'k2' MATCH (b) where b.name = 'p5' CREATE (a)-[:HAS]->(b);
MATCH (a) WHERE a.name = 'k2' MATCH (b) where b.name = 'p7' CREATE (a)-[:HAS]->(b);
MATCH (a) WHERE a.name = 'k2' MATCH (b) where b.name = 'p6' CREATE (a)-[:HAS]->(b);

创建顺序很重要,因为我看到 Neo4j 在没有其他排序时按 id 对结果进行排序,这可以给出提示:当发出的查询错误时,节点会以错误的顺序返回。

您应该想出以下图形表示:

Resulting graph

我需要按照 k1 给出的顺序提取 kNows 拥有的节点(并且只有那些),所以:

f1 <- m2 <- b3 <- d4

我的目标是获得一个程序可以处理的结果,所以我的第一个想法是一个数组,如:[f1,m2,b3,d4],但当然这可能不是最好的,也可能根本不支持

>

请注意,我也需要路径的头部,f1,即没有传出 kNows 关系的节点。

下一步将是一个返回对(节点,关系道具)的查询,因为在上面的真实图中,关系具有我也需要处理的属性

所以我想从图中获得的完整结果应该是这样的:[[f1,{}],[m2,{type: friend}],[b3,{type: sibling}],[d4,{type: coworker}]]

但是,可以像下面的伪代码那样处理的任何结果格式都可以:

for x in [result] do:
    if(x.type.isEmpty) {
        // process the head
    } else if (x.type == "friend") {
        // do something kNowing this node is a friend of the preceding one
    } else ...

更新

经过一些尝试,我想出了以下两个查询

(1)

match p=(a:temporary)-[:KNowS*0..]->(b) 
where not ()-[:KNowS]->(a) and not (b)-[:KNowS]->() 
and exists { match (k)-[:HAS]->(a) where k.name='k1' } 
return p

这个结果是一条真实的路径——虽然中间节点重复了,即... {"type":"coworker"},{"name":"b3"},{"type":"sibling"} ...,我不知道是设计的还是我弄错了——返回的结果只有一个并且它的元素顺序正确(虽然它从尾部开始,但我想这可以在程序中轻松处理),从图表中感觉更“自然”,更安全(没有出现错误的风险)后来,在图表随着使用而增长之后):

╒══════════════════════════════════════════════════════════════════════╕
│"p"                                                                   │
╞══════════════════════════════════════════════════════════════════════╡
│[{"name":"d4"},{"type":"coworker"},{"type"│
│:"sibling"},{"name":"m2"},{"type":"friend"},{"name":"f1"│
│}]                                                                    │
└──────────────────────────────────────────────────────────────────────┘

(2)

match p=(a)-[:KNowS*0..]->(b)
where 
not (b)-[:KNowS]->()
and exists { match (k)-[:HAS]->(a) where k.name='k1' }
with  a,head(relationships(p)) as h,size(relationships(p)) as s
return a,h,s
order by s

这反而给出了我想要的形状的结果(成对的(节点,关系)——忽略 s 列,它只是为了检查它的值),尽管实际上找到了几个路径(所有那些来自组中的每个节点 kNownk1 转到头部 f1) 并且我需要操纵它们中的每一个以将一个节点与其最接近的关系配对并对结果进行排序从最靠近头部到最远):

╒═════════════╤═══════════════════╤═══╕
│"a"          │"h"                │"s"│
╞═════════════╪═══════════════════╪═══╡
│{"name":"f1"}│null               │0  │
├─────────────┼───────────────────┼───┤
│{"name":"m2"}│{"type":"friend"}  │1  │
├─────────────┼───────────────────┼───┤
│{"name":"b3"}│{"type":"sibling"} │2  │
├─────────────┼───────────────────┼───┤
│{"name":"d4"}│{"type":"coworker"}│3  │
└─────────────┴───────────────────┴───┘

现在我无法分辨哪个是正确使用的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。