有几点需要澄清:
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 这样的横向扩展分布式数据库,您需要先了解工作负载,然后优化数据模型以适应工作负载(而不是先思考实体)。您需要记住,集合只是一个逻辑抽象,由位于分区集中的许多副本组成。它们不强制执行架构并且是查询的边界。
在设计模型时,您需要将以下问题纳入您的思考过程:
以上内容应该会影响您对分区键的选择以及您的数据/对象模型应该是什么样子。例如:
- 请求的比率将有助于指导您如何进行权衡(使用 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"