【问题标题】:self-join on documentdb syntax errordocumentdb 语法错误时的自联接
【发布时间】:2021-09-30 08:21:07
【问题描述】:

我在 documentdb 上执行其他 SQL 有效的自联接查询时遇到问题。

所以以下查询有效: SELECT * FROM c AS c1 WHERE c1.obj="car"

但是这个简单的自连接查询没有:SELECT c1.url FROM c AS c1 JOIN c AS c2 WHERE c1.obj="car" AND c2.obj="person" AND c1.url = c2.url,错误为Identifier 'c' could not be resolved

It seemsdocumendb 支持文档内的自联接,但我是在集合级别询问。

看了一下官方syntax doc,了解到集合名称基本是推断出来的;我尝试将 c 更改为明确我的集合名称和根目录,但均未成功。

我是否遗漏了一些明显的东西?谢谢!

【问题讨论】:

  • 您当前的查询看起来对任何普通的关系数据库都有效。也许有一些你不知道的自我加入限制。
  • hm,他们似乎不支持集合之间的连接;哇,这么小的功能...stackoverflow.com/questions/32604279/…
  • 这可能是有原因的; SQL 接口可能会误导我们。

标签: join azure-cosmosdb


【解决方案1】:

有几点需要澄清:

1.) 关于Identifier 'c' could not be resolved

查询范围为单个集合;在上面的示例中,c 是集合的隐式别名,该集合使用 AS 关键字重新别名为 c1

您可以修复示例查询,将 JOIN 更改为引用 c1

SELECT c1.url
FROM c AS c1
JOIN c1 AS c2
WHERE c1.obj="car" AND c2.obj="person" AND c1.url = c2.url`

这也相当于:

SELECT c1.url
FROM c1
JOIN c1 AS c2
WHERE c1.obj="car" AND c2.obj="person" AND c1.url = c2.url`

2.) 了解 JOIN 并检查您的数据模型

话虽如此,我认为修复上述查询语法问题不会产生您所期望的行为。 DocumentDB SQL 中的JOIN 关键字旨在与文档中的非规范化元素数组形成叉积(而不是在同一集合中的其他文档之间形成叉积)。如果您在这里遇到困难,可能值得退后一步,重新审视如何为 Azure Cosmos DB 建模数据。

在 RDBMS 中,您被训练为以实体为先并基于实体规范化您的数据模型。您严重依赖查询引擎来优化查询以适应您的工作负载(这通常可以很好地完成检索数据的工作,但并不总是最佳)。这里的挑战是,随着规模的增加,许多关系收益会丢失,并且需要扩展到多个分片/分区。

对于像 Cosmos DB 这样的横向扩展分布式数据库,您需要先了解工作负载,然后优化数据模型以适应工作负载(而不是先思考实体)。您需要记住,集合只是一个逻辑抽象,由位于分区集中的许多副本组成。它们不强制执行架构并且是查询的边界。

在设计模型时,您需要将以下问题纳入您的思考过程:

  • 就规模和吞吐量而言,更广泛的解决方案的规模是多少(估计数量级就足够了)?

  • 读取与写入的比率是多少?

  • 对于写入 - 写入的模式是什么?主要是插入,还是有很多更新?

  • 对于读取 - 前 N 个查询是什么样的?

以上内容应该会影响您对分区键的选择以及您的数据/对象模型应该是什么样子。例如:

  • 请求的比率将有助于指导您如何进行权衡(使用 Pareto 原则并针对您的大部分工作负载进行优化)。
  • 对于读取繁重的工作负载,通常过滤的属性成为选择分区键的候选者。
  • 应在数据模型中将倾向于一起频繁更新的属性一起抽象出来,并远离以较慢节奏更新的属性(以降低更新的 RU 费用)。
  • 不要害怕复制属性以丰富不同记录类型的可查询性和注释类型。例如,我们有两种类型的文档:cat 和 person。

    {
       "id": "Andrew",
       "type": "Person",
       "familyId": "Liu",
       "employer": "Microsoft"
    }
     
    {
       "id": "Ralph",
       "type": "Cat",
       "familyId": "Liu",
       "fur": {
             "length": "short",
             "color": "brown"
       }
    }
     

我们无需JOIN就可以查询这两种类型的文档,只需运行一个不带过滤器类型的查询:

SELECT * FROM c WHERE c.familyId = "Liu"

如果我们想过滤 type = “Person”,我们可以简单地在我们的查询中添加一个过滤器:

SELECT * FROM c WHERE c.familyId = "Liu" AND c.type = "Person"

【讨论】:

  • 虽然作为 db 的研究生,我必须说具有 6 范式的 LogicBlox 人可能会不同意你的观点! :P
【解决方案2】:

Above Answer 有@Andrew Liu 提到的问题。这将解决您的错误,但 Azure Cosmos DB 不支持跨项目和跨容器联接。使用此链接了解加入 https://docs.microsoft.com/en-us/azure/cosmos-db/sql/sql-query-join

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 根据时间流逝和用户选择的顺序,没有单一的顺序或“高于”或“低于”的答案,点击“分享”以获得答案的链接。
猜你喜欢
  • 2019-06-21
  • 1970-01-01
  • 2014-11-23
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多