自加入 documentdb 语法错误

yif*_*nwu 3 join azure-cosmosdb

我在 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

似乎documendb 支持文档内的自联接,但我问的是集合级别。

看了官方的syntax doc,了解到集合名称基本是推断出来的;我尝试c明确更改为我的收藏名称和根,但都没有奏效。

我错过了一些明显的东西吗?谢谢!

And*_*Liu 5

有几点需要澄清:

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

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

您可以修复示例查询,将 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`
Run Code Online (Sandbox Code Playgroud)

这也相当于:

SELECT c1.url
FROM c1
JOIN c1 AS c2
WHERE c1.obj="car" AND c2.obj="person" AND c1.url = c2.url`
Run Code Online (Sandbox Code Playgroud)

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

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

在 RDBMS 中,您接受过以实体为先的训练,并根据实体对数据模型进行规范化。您严重依赖查询引擎来优化查询以适应您的工作负载(通常可以很好地但并不总是最佳的数据检索工作)。这里的挑战是,随着规模的增加,许多关系优势会消失,扩展到多个分片/分区成为一种要求。

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

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

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

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

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

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

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

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

    {
       "id": "Andrew",
       "type": "Person",
       "familyId": "Liu",
       "employer": "Microsoft"
    }
     
    {
       "id": "Ralph",
       "type": "Cat",
       "familyId": "Liu",
       "fur": {
             "length": "short",
             "color": "brown"
       }
    }
     
Run Code Online (Sandbox Code Playgroud)

我们可以查询这两种类型的文档,而无需JOIN简单地运行一个没有类型过滤器的查询:

    {
       "id": "Andrew",
       "type": "Person",
       "familyId": "Liu",
       "employer": "Microsoft"
    }
     
    {
       "id": "Ralph",
       "type": "Cat",
       "familyId": "Liu",
       "fur": {
             "length": "short",
             "color": "brown"
       }
    }
     
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM c WHERE c.familyId = "Liu"
Run Code Online (Sandbox Code Playgroud)