【问题标题】:Efficient ArangoDB AQL query that can find all Edges in Collection that go To and From the same Documents高效的 ArangoDB AQL 查询,可以找到集合中去往和来自相同文档的所有边
【发布时间】:2021-04-23 20:52:36
【问题描述】:

我有一个包含两个集合的 ArangoDB,一个用于文档,一个用于边缘,我想要一个高效的查询,它只返回共享相同 _to_from 值的边缘。

例如,假设我的文档集合包含 A、B、C 和 D。 我们还假设我的 Edges 集合包含 X、Y 和 Z。

边 X 是 _from A 和 _to B。

边 Y 也是 _from A 和 _to B。

边 Z 是 _from C 和 _to D。

但是我不知道X和Y是基本相同的Edge,也不知道共享相似Edge的Document是A&B。我的查询是找出这些重复的Edge。

我目前的样子是这样的:

FOR ec1 IN edge_collection
    FOR ec2 IN edge_collection
        FILTER ec1._key != ec2._key AND ec1._to == ec2._to AND ec1._from == ec2._from
        RETURN ec1

这似乎有效,尽管它也感觉非常低效。有没有更好的方法来做到这一点,或者这是 AQL 的最佳解决方案?

【问题讨论】:

    标签: arangodb aql


    【解决方案1】:

    您可以按_from_to 进行分组,计算每组有多少条边,并过滤掉唯一的组合:

    FOR ec IN edge_collection
      COLLECT from = ec._from, to = ec._to WITH COUNT INTO count
      FILTER count > 1
      RETURN { from, to, count }
    

    或者如果您也想返回边缘键:

    FOR ec IN edge_collection
      COLLECT from = ec._from, to = ec._to INTO edges = ec._key
      LET count = LENGTH(edges)
      FILTER count > 1
      RETURN { from, to, count, edges }
    

    或者使用聚合而不是后计算:

    FOR ec IN edge_collection
      COLLECT from = ec._from, to = ec._to AGGREGATE count = LENGTH(1) INTO edges = ec._key
      FILTER count > 1
      RETURN { from, to, count, edges }
    

    要返回完整的边缘,请改用INTO edges = ec。你也可以只使用INTO edges,但是每条边都将嵌套在一个对象{"ec": … }中。

    【讨论】:

      【解决方案2】:

      经过更多的挖掘,我发现了一种使用COLLECT 语句的明显更快的方法。

      另外,完全披露,这是我在 this other answer 的基础上构建的。

      LET duplicates = (
          FOR ec IN edge_collection
              COLLECT from = ec._from, to = ec._to WITH COUNT INTO count
              FILTER count > 1
              RETURN {
                  from: from,
                  to: to,
                  count: count
              }
      )
      
      FOR d IN duplicates
          FOR ec IN edge_collection
              FILTER d.from == ec._from AND d.to == ec._to
              RETURN ec
      

      编辑:

      基于@CodeManX 的回答,我的最终目标是能够删除或者更确切地说REMOVE 这些重复值。如果有人出于类似的目标偶然发现此问题,这可能会有所帮助:

      LET duplicates = (
          FOR ec IN edge_collection
              COLLECT from = ec._from, to = ec._to AGGREGATE count = LENGTH(1) INTO edges = ec._key
              FILTER count > 1
              RETURN { from, to, count, edges }
      )
      
      FOR d IN duplicates
          LET key_to_delete = FIRST(d.edges)
          REMOVE { _key: key_to_delete } IN edge_collection
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2021-09-17
      • 1970-01-01
      相关资源
      最近更新 更多