我在Cosmos DB中有一个集合,其中文档分为两种类型。我们称他们为board
和pin
。
板:
{
"id": "board-1",
"description": "A collection of nice pins",
"author": "user-a",
"moments": [
{
"id": "pin-1"
},
{
"id": "pin-2"
},
{
"id": "pin-3"
}
]
}
固定
{
"id": "pin-1",
"description": "Number 1 is the best pin",
"author": "user-b"
}
我知道如何根据id查询一个引脚板。但我需要查询(基于电路板的ID),它给出了电路板中包含的所有引脚。如果我可以过滤出Pins的一个或多个部分也会很好。
示例:不将作者返回给客户端。
{
"id": "pin-1",
"description": "Number 1 is the best pin"
},
{
"id": "pin-2",
"description": "Number 2 is very funny"
}..etc
我知道我可以通过发出两个请求在客户端应用程序中处理这个逻辑,但是是否可以为处理此问题的Cosmos DB编写查询?
答案 0 :(得分:2)
简答:不,目前您无法在单个SQL查询中加入不同的文档。
DocumentDB是无模式的,并且在关系数据库世界中没有“引用”的硬概念。您在文档中的引用ID只是DocumentDB的常规字符串数据,它们的特殊含义(链接到其他文档)仅存在于您的应用程序中。查询当前只是通过某些给定谓词查找文档或文档的一部分。它是在文档上相互独立地执行的。
作为旁注:我认为这是设计因为这样的选择限制使并行性的潜力成为可能,并且可能有助于他们打算实现的低延迟梦想。
这并不意味着你所需要的是不可能的。要考虑的选项:
选项1:参考重新设计
如果您的数据设计中board
- bin
关系数据存储在pin
- 侧,那么您可以查询board-1
中的所有引脚使用单个查询,沿着以下行:
select * from pin where pin.boardId = @boardId
您需要在某种程度上对数据模型进行非规范化以优化RU使用情况,这是很常见的。有时将一些父信息复制到引用文档是有益的。如果数据不是太不稳定并且从双方都被大量阅读,甚至可以将关系存储在两端。作为一个缺点,保持数据在写入时同步变得有点复杂。嗯,权衡......
如果重新设计是一个选项,那么请参阅谈话Modeling Data for NoSQL Document Databases from //build/2016 by Ryan CrawCour and David Makogon。它应该给你一些想法。
在为documentdB设计数据时,请记住,在DocumentDB存储相对便宜的情况下,处理能力(RU)就是你付出的代价。
选项2:存储过程
如果您希望/需要优化存储/延迟并且无法修改数据设计并且真正需要在单个往返中执行此类查询,那么您可以构建存储过程以在服务器端执行查询然后打包结果在DocumentDB中返回单个返回的Json消息。
有关可以做什么以及如何做的详细信息,请参阅Azure Cosmos DB server-side programming: Stored procedures, database triggers, and UDFs。
我想你可能会获得稍微好一点的延迟(由于单次调用)和整体RU使用稍差(SP执行,事务,合并结果的额外工作),但绝对在提交之前测试你的情况。
我认为这个选项有点脏: 1.按更高级别需求组合文档是逻辑,因此不应在数据库中实现,而应与应用程序逻辑层实现。 1. DocumentDB中的JS开发,调试和维护更加繁琐。
选项3:不做任何改变
..只做2个电话。它很简单,从长远来看可能最终成为最佳解决方案(考虑到设计,开发,维护,变更等的总体成本......)。