1

我们正在使用层次结构树结构,其中父级有零个或多个子级,而一个子级有一个或零个父级。当我们查询给定父级的直接子级列表时,查询会以随机顺序返回子级。我们需要孩子按照我们在创建或更新孩子时定义的顺序返回。

我在孩子之间添加了关系 -[:Sibling]-> 所以“顶部”兄弟只有一个传入的 :Sibling 关系,而“底部”兄弟只有一个传出关系。

鉴于此,是否有一个 Cypher 查询以兄弟顺序返回子级?

我有一个返回每个孩子及其兄弟的查询,但现在我必须编写一些代码以正确的顺序返回列表。

另一种方法可能是为每个子节点添加一个排序号。如果其中一个孩子更改顺序,则需要为所有孩子更新。这种方法似乎对图形数据库概念有点陌生。

如果以前遇到过这个问题,是否有标准的算法来以编程方式解决它?


更新1

布鲁诺要求的样本数据

(parent1) (child1)-[:ChildOf]->(parent1) (child2)-[:ChildOf]->(parent1) (child2)-[:Sibling]->(child1) (child3)-[:ChildOf]->(parent1) (child3)-[:Sibling]->(child2)

是否有密码查询以该顺序返回 child1、child2、child3?

如果不是,则可以通过编程方式进行排序

使用属性而不是关系 (parent1) (child1)-[:ChildOf]->(parent1) (child1:{order:1}) (child2)-[:ChildOf]->(parent1) (child2:{order:2}) (child3)-[:ChildOf]->(parent1) (child3:{order:3})

`match (c)-[:ChildOf]->(parent1) return c ordered by c:order`

我不希望有一个可以更新孩子顺序的密码查询。


更新2

我现在已经到达以下查询,它以正确的顺序返回子项

`match (firstChild)-[:FirstChildOf]->(parent) match (sibling)-[:Sibling*]->(firstChild) return firstChild,sibling`

此查询依赖于添加 -[:FirstChildOf]->(parent) 关系。

如果我没有听到,否则我会将其设置为答案。

我应该假设没有用于将节点插入有序列表的密码查询吗?

4

3 回答 3

1

当你创建你的图模型时,你应该专注于你想用你的数据模型回答的问题。如果您想获取通过“创建或更新”属性排序的父级的子级,那么您应该存储它,因为该关系通常不代表订单。它与图数据库概念并不陌生,因为图数据库使用属性。决定将某些东西存储为关系或属性并不总是一件容易的事。这一切都与正确的建模有关。如果你有 '[:NEXT_SIBLING]' 或类似的概念,那么当你必须删除一个节点时,这将是一个痛苦的过程。所以我应该在这个状态不变的时候使用它。例如,在时间树中,日子是接踵而至的,并且不会改变。

一般来说,如果应该使用创建顺序,我应该使用这样的时间戳:

    create (n:Node {created:timestamp()});

然后您可以使用时间戳来订购。

    match (p:Parent)-[:HAS_CHILDREN]->(n:Child) where p.name='xy' return n order by n.created;

您也可以将时间戳用于关系。类似的问题在这里: Modeling an ordered tree with neo4j

于 2017-08-17T17:10:16.547 回答
0

以正确顺序返回孩子的查询是

match (firstChild)-[:FirstChildOf]->(parent) match (sibling)-[:Sibling*]->(firstChild) return firstChild,sibling
于 2017-08-25T16:02:02.197 回答
0

以下是我在处理 Neo4J 中节点的有序列表时使用的一些技巧。

  • 将关系方向反转为(child1)<-[:HasChild]-(parent1)。(主要是对下一个项目的逻辑强化,因为“父母有孩子的名单”)

  • 将属性添加index到 HasChild。这将让你WITH child, hasChild.index as sid ORDER BY sid ASC为兄弟订单做。(这就是我在子列表上维护任意顺序信息的方式)这是关于关系的,因为它假设一个节点可以是多个有序列表的一部分。

  • 您可以使用SIZE(shortestpath((root)-[*]->(child1)) as depth来按深度从根开始对它们进行排序。

  • 由于这是针对任意顺序的,因此您必须更新所有索引以更新顺序(您可以WITH COLLECT(child) as children, FILTER(c IN COLLECT(child) WHERE c.index >=3) as subset FOREACH (c IN subset| SET c.index+=1)对基本插入执行类似操作,否则您将不得不全部重写它们以任意更改顺序。

  • 如果您实际上并不关心顺序,只要它是一致的,您可以使用WITH child, ID(child) as sid ORDER BY sid ASC. 这本质上是“按节点年龄排序”

  • 另一种选择是使用元关系。So:HasChild将充当节点列表,然后类似的:NextMember内容会告诉您该节点的下一个项目是什么。这更灵活,但在我看来更难使用(你需要 case for doesn't have next,为了获得正确的顺序,你必须在节点上进行“跟踪”,如果你想这样做就行不通稍后将此节点添加到另一个有序列表中,等等。)

当然,如果顺序不是任意的(基于姓名或年龄等),那么仅按非任意逻辑排序要好得多。

于 2017-08-18T14:18:19.783 回答