Arangodb AQL 连接、合并、嵌入嵌套的三个或更多集合

Posted

技术标签:

【中文标题】Arangodb AQL 连接、合并、嵌入嵌套的三个或更多集合【英文标题】:Arangodb AQL Joining, merging, embedding nested three collections or more 【发布时间】:2021-11-05 02:14:12 【问题描述】:

我有以下集合,基于示例 Arangodb doc here,但添加了第三个名为 region 的集合

Users
 
  "name" :  
    "first" : "John", 
    "last" : "Doe" 
  , 
  "city" : "cities/2241300989", 
  "_id" : "users/2290649597", 
  "_rev" : "2290649597", 
  "_key" : "2290649597" 


Cities
 
  "population" : 1000, 
  "name" : "Metropolis", 
  "region" : "regions/2282300990", 
  "_id" : "cities/2241300989", 
  "_rev" : "2241300989", 
  "_key" : "2241300989" 



Regions
  
  "name" : "SomeRegion1", 
  "_id" : "regions/2282300990", 
  "_rev" : "2282300990", 
  "_key" : "2282300990" 
 

我想要一个像这样的目标结果

[ 
   
    "user" :  
      "name" :  
        "first" : "John", 
        "last" : "Doe" 
      , 
      "_id" : "users/2290649597", 
      "_rev" : "2290649597", 
      "_key" : "2290649597" 
    , 
    "city" :  
      "population" : 1000, 
      "name" : "Metropolis",
      "_id" : "cities/2241300989", 
      "_rev" : "2241300989", 
      "_key" : "2241300989",
      "region" : 
          "name" : "SomeRegion1", 
          "_id" : "regions/2282300990", 
          "_rev" : "2282300990", 
          "_key" : "2282300990" 
      
     
   
]

Arangodb 文档here 中的示例只有两个集合的查询

FOR u IN users 
    FOR c IN cities 
        FILTER u.city == c._id  RETURN merge(u, city: c)

# However I want to have more than two collections e.g.
FOR u IN users 
  FOR c IN cities 
    For r IN regions
      FILTER u.city == c._id and c.region == r._id RETURN merge(????????)

如上加入三个集合,您将如何获得结果?如果我想要第四个嵌套的会怎样?

【问题讨论】:

【参考方案1】:

当您存储引用另一个集合的文档 _id 时,您可以利用 DOCUMENT AQL 命令。

所以你的 AQL 查询变得更简单了,像这样:

FOR u IN users
  LET city = DOCUMENT(u.city)
  LET city_with_region = MERGE(city,  region: DOCUMENT(city.region)
  RETURN MERGE(u,  city: city_with_region)

这个查询可以折叠得更多,但我把它留成这样,这样它就更能自我记录了。

DOCUMENT 的酷之处在于您只能返回文档的单个属性,例如 LET region_name = DOCUMENT(city.region).name

我还发现,在大多数情况下,执行子查询来定位文档的性能更高。

【讨论】:

请注意,原始查询使用子查询,而是嵌套的FORs,类似于SQL中的JOIN。如果可能,这是首选解决方案,因为它通常比子查询或 DOCUMENT 函数调用执行得更好。此外,由于引入了拼接子查询,子查询的性能要好得多。您还应该注意,在集群中,带有 id 的 DOCUMENT 调用不能推送到 DB 服务器,而必须在协调器上执行。 顺便说一句,您也可以在使用嵌套查询或子查询时只返回一个属性。根据可能使用的索引,有问题的字段可能会从索引中获取,因此可能不需要加载完整的文档。但是,通过 DOCUMENT 调用获取文档总是会加载整个文档。 这真的取决于您的完整用例,当它超出此处发布的初始问题时。始终进行性能测试,关注 CPU/RAM/HDD 使用率、查询性能、单/集群性能、索引优化、数据存储重组以及从许多小文档到许多大文档的各种集合格式。每个人的里程会有所不同,测试和测试更多。 我同意您应该始终进行自己的性能测试。也就是说,嵌套 FOR 为查询优化器提供了最好的基础,因此应该几乎总是表现最好。 我有一些大型查询,200 多行 AQL,有趣的是,DOCUMENT 命令明显更快,尤其是在深度嵌套的循环中。我还尝试在查询中使用 Dictionary 样式对象生成来进行字典查找,但令人惊讶的是 DOCUMENT 命令比字典或嵌套 FOR 更快。测试显示了惊人的事情。【参考方案2】:

大概是这样的:

FOR u IN users 
  FOR c IN cities 
    For r IN regions
      FILTER u.city == c._id AND c.region == r._id
      RETURN  user: u, city: MERGE(c, region: r  

您存储 id 而不是键来引用城市和地区是否有特殊原因? _id 只是一个虚拟字段,由集合名称前缀的 _key 组成(加上一个斜杠)。所以这同样有效(我故意省略了内部的 _id 和 _rev 字段):

Users
 
  "name" :  
    "first" : "John", 
    "last" : "Doe" 
  , 
  "city" : "2241300989", 
  "_key" : "2290649597"


Cities
 
  "population" : 1000, 
  "name" : "Metropolis", 
  "region" : "2282300990",
  "_key" : "2241300989" 



Regions
  
  "name" : "SomeRegion1",
  "_key" : "2282300990"


FOR u IN users 
  FOR c IN cities 
    For r IN regions
      FILTER u.city == c._key AND c.region == r._key
      RETURN  user: u, city: MERGE(c, region: r  

【讨论】:

谢谢你,但目标回报与我所寻找的不符。 为什么不匹配?它与您的预期结果有何不同?

以上是关于Arangodb AQL 连接、合并、嵌入嵌套的三个或更多集合的主要内容,如果未能解决你的问题,请参考以下文章

ArangoDB AQL 深度数组扫描

如何在 ArangoDB AQL 查询中获取第一个和最后一个条目

ArangoDB图数据库--总参

用python操作和管理ArangoDB

arangodb自定义函数

ArangoDB 中的正文参数