Neo4j命令树

时间:2017-08-17 13:26:29

标签: neo4j tree cypher ordered-tree

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

我添加了孩子之间的关系 - [:兄弟姐妹] - >所以' top'兄弟姐妹只有一个传入:兄弟姐妹关系,以及'底部'兄弟姐妹只有外向的关系。

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

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

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

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

UPDATE1

根据Bruno的要求

示例数据

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

是否有一个cypher查询以按顺序返回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`

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

UPDATE2

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

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

此查询取决于添加 - [:FirstChildOf] - >(父)关系。

如果我没有听到其他声音,我会将其设置为答案。

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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。这基本上是“逐个节点年龄”

  • 另一个选择是使用元关系。所以:HasChild将充当节点列表,然后像:NextMember这样的东西会告诉你这个节点的下一个项目是什么。这更灵活,但在我看来更难以使用(你需要为没有下一个的情况,为了获得正确的顺序,你必须在节点上做'跟踪',如果你想要的话不起作用稍后将此节点添加到另一个有序列表,等等。

当然,如果订单不是任意的(基于名称或年龄等),那么只需对非任意逻辑进行排序就好了。

答案 2 :(得分:0)

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

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