4

我正在尝试使用 Neo4j 来分析家谱中的关系。我已经这样建模了:

(p1:Person)-[:CHILD]->(f:Family)<-[:FATHER|MOTHER]-(p2)

我知道我可以省略家庭标签,让孩子与每个父母都有联系,但这对我的目的不切实际。这是我的图表示例,黑线是我希望它生成的路径:

全树

我可以查询它

MATCH p=(n {personID:3})-[:CHILD]->()<-[:FATHER|MOTHER]-()-[:CHILD]->()<-[:FATHER|MOTHER]-()-[:CHILD]->()<-[:FATHER|MOTHER]-() RETURN p

但是这种关系有一个重复的模式。我可以做类似的事情:

MATCH p=(n {personID:3})(-[:CHILD]->()<-[:FATHER|MOTHER]-())* RETURN p

其中 * 表示重复 :CHILD 然后 :FATHER|MOTHER 关系,方向不同?显然,如果关系都是同一个方向,我可以使用

-[:CHILD|FATHER|MOTHER*]->

我希望能够像谱系图一样从第 3 个人一直查询到图表顶部,但如果需要,还可以具体说明多少级别(例如 3 代,而不是行尾) .

我遇到的另一个问题是,如果我不在关系上设置方向,-[:CHILD|FATHER|MOTHER*]-例如链查找所有其他“表亲、阿姨、叔叔等”。

任何经验丰富的 Cypher 专家可以帮助我吗?

4

4 回答 4

2

我只是在同样的问题上。我发现APOC 扩展路径程序正在完成您/我们想要的。

应用于您的示例,您可以使用apoc.path.subgraphNodes获取 Person #3 的所有祖先:

MATCH (p1:Person {personId:3})
CALL apoc.path.subgraphNodes(p1, {
    sequence: '>Person,CHILD>,Family,<MOTHER|<FATHER'
}) YIELD node
RETURN node

或者,如果您只想要从起始人到 3 代的祖先,请添加maxLevel: 6到配置(因为 1 代由 2 个关系定义,3 代是 6 个级别):

MATCH (p1:Person {personId:3})
CALL apoc.path.subgraphNodes(p1, {
    sequence: '>Person,CHILD>,Family,<MOTHER|<FATHER',
    maxLevel: 6
}) YIELD node
RETURN node

如果您只想要第 3 代的祖先,即只想要曾祖父母,您还可以指定minLevel(使用apoc.path.expandConfig):

MATCH (p1:Person {personId:3})
CALL apoc.path.expandConfig(p1, {
    sequence: '>Person,CHILD>,Family,<MOTHER|<FATHER',
    minLevel: 6,
    maxLevel: 6
}) YIELD path
WITH last(nodes(path)) AS person
RETURN person
于 2018-07-12T12:01:47.790 回答
1

您可以反转CHILD模型中关系的方向性,如下所示:

(p1:Person)<-[:CHILD]-(f:Family)<-[:FATHER|MOTHER]-(p2)

这样,您可以-[:CHILD|FATHER|MOTHER*]->在查询中使用简单的模式。

反转方向性实际上也很直观,因为您可以更自然地将图形可视化为家谱,所有箭头从祖先“向下”流向后代。

于 2015-05-20T18:27:27.713 回答
0

是的,这是一个有趣的案例。我很确定(尽管我愿意纠正)这是不可能的。你有可能同时拥有并维持两者吗?你可以有一个简单的密码查询来创建额外的关系:

MATCH (parent)-[:MOTHER|FATHER]->()<-[:CHILD]-(child)
CREATE (child)-[:CHILD_OF]->parent
于 2015-05-20T18:01:18.097 回答
0

好的,所以这里有一个想法:

MATCH path=(child:Person {personID: 3})-[:CHILD|FATHER|MOTHER*]-(ancestor:Person),
WHERE ancestor-[:MOTHER|FATHER]->()
RETURN path

通常我会MATCH像这样使用第二个子句:

MATCH
  path=(child:Person {personID: 3})-[:CHILD|FATHER|MOTHER*]-(ancestor:Person),
  ancestor-[:MOTHER|FATHER]->()
RETURN path

但是 Neo4j(至少默认情况下,我认为)不会遍历路径。也许逗号分隔会很好,这将是一个问题:

MATCH path=(child:Person {personID: 3})-[:CHILD|FATHER|MOTHER]-(ancestor:Person)-[:MOTHER|FATHER]->()

我很想知道你发现了什么!

于 2015-05-20T18:12:00.880 回答