Cross JOIN 集合和 Group By Cosmos DB Javascript API
Cross JOIN collections and GroupBy CosmosDB Javascript API
我正在 Javascript API 中搜索 CosmosDB 的解决方案,您可以在其中执行两个文档集合之间的 INNER/OUTER JOIN。
我没有成功。
据我了解,Javascript 存储过程 运行 在一个集合中,不能 access/reference 另一个集合中的数据。
如果上述情况属实,那么我们的应用程序数据源以关系方式设计的数据源位于何处?如果业务需要立即查询,收集以下数据:
所有 agreements/contracts 已在给定时间范围内迁移到特定区域内的新产品。如果大约有 5 个集合包含与此查询相关的所有信息,我将如何处理此查询?
有指导吗?
更新
客户
{
"id": "d02e6668-ce24-455d-b241-32835bb2dcb5",
"Name": "Test User One",
"Surname": "Test"
}
协议
{
"id": "ee1094bd-16f4-45ec-9f5e-7ecd91d4e729",
"CustomerId": "d02e6668-ce24-455d-b241-32835bb2dcb5"
"RetailProductVersionInstance":
[
{
"id": "8ce31e7c-7b1a-4221-89a3-449ae4fd6622",
"RetailProductVersionId": "ce7a44a4-7e49-434b-8a51-840599fbbfbb",
"AgreementInstanceUser": {
"FirstName": "Luke",
"LastName": "Pothier",
"AgreementUserTypeId": ""
},
"AgreementInstanceMSISDN": {
"IsoCountryDialingCode": null,
"PhoneNumber": "0839263922",
"NetworkOperatorId": "30303728-9983-47f9-a494-1de853d66254"
},
"RetailProductVersionInstanceState": "IN USE",
"IsPrimaryRetailProduct": true,
"RetailProductVersionInstancePhysicalItems": [
{
"id": "f8090aba-f06b-4233-9f9e-eb2567a20afe",
"PhysicalItemId": "75f64ab3-81d2-f600-6acb-d37da216846f",
"RetailProductVersionInstancePhysicalItemNumbers": [
{
"id": "9905058b-8369-4a64-b9a5-e17e28750fba",
"PhysicalItemNumberTypeId": "39226b5a-429b-4634-bbce-2213974e5bab",
"PhysicalItemNumberValue": "KJDS959405"
},
{
"id": "1fe09dd2-fb8a-49b3-99e6-8c51df10adb1",
"PhysicalItemNumberTypeId": "960a1750-64be-4333-9a7f-c8da419d670a",
"PhysicalItemNumberValue": "DJDJ94943"
}
],
"RetailProductVersionInstancePhysicalItemState": "IN USE",
"DateCreatedUtc": "2018-11-21T13:55:00Z",
"DateUpdatedUtc": "2020-11-21T13:55:00Z"
}
]
}
]
}
RetailProduct
{
"id": "ce7a44a4-7e49-434b-8a51-840599fbbfbb",
"FriendlyName": "Data-Package 100GB",
"WholeSaleProductId": "d054dae5-173d-478b-bb0e-7516e6a24476"
}
批发产品:
{
"id": "d054dae5-173d-478b-bb0e-7516e6a24476",
"ProductName": "Data 100",
"ProviderLiabilities": []
}
上面,我添加了一些示例文档。
关系:
- Agreement.CustomerId 链接到 Customer.id
- Agreement.RetailProductVersionInstance.RetailProductVersionId 个链接
至 RetailProduct.id
- RetailProduct.WholeSaleProductId 链接到 WholeSaleProduct.id
我如何在 CosmosDB 中编写 Javascript 存储过程来执行这 4 个集合之间的连接?
简而言之,您不能通过 Cosmos DB 中的 SQL 在不同集合之间执行连接。
一般来说,这类问题的解决方案是多次查询或者不同的schema。在您的场景中,如果您可以在不复制数据的情况下将架构反规范化为一个集合,那么这很容易。
如果您提供架构,则可能会提供更全面的答案。
-- 编辑 1 --
存储过程仅适用于需要对同一集合 + 分区键执行多项操作的操作。这使得它们非常适合批量 insert/delete/update、事务(至少需要一次读取和一次写入)以及其他一些事情。它们不适用于 CPU 密集型事物,而是通常受网络延迟限制的 IO 事物。它们不可能用于跨分区或跨集合场景。在这些情况下,您必须专门从远程客户端执行操作。
对于您的情况,这是相当简单的 2 + 2N
单独读取,其中 N
是产品数量。您需要先阅读协议。然后你可以并行查找客户和产品记录,然后你可以最后查找批发记录,所以你应该有 3s + C
的延迟,其中 s
是平均持续时间给定读取请求并且 C
是某个常量 CPU 执行 join/issue 和 request/etc.
的时间
值得考虑的是,您是否可以将 RetailProduct 和 WholeSale 产品合并到单个记录中,其中 Wholesale 包含数组中的所有 RetailProducts,或者作为单独的文档,按批发 ID 分区,具有包含 Wholesale 的众所周知的 ID单独文档中的产品信息。这将使您的延迟减少三分之一。如果您采用按批发 ID 进行分区的想法,您可以为共享批发 ID 的任何记录编写 1 个查询,这样您将获得 2 + log(N)
次读取,但有效延迟相同。对于该策略,您将在协议中存储 "wholesaleid+productid" 的复合索引。一个值得担心的问题是它复制了批发+产品关系,但只要这种关系不改变,我认为没有什么可担心的,它为信息查找提供了很好的优化。
我正在 Javascript API 中搜索 CosmosDB 的解决方案,您可以在其中执行两个文档集合之间的 INNER/OUTER JOIN。
我没有成功。
据我了解,Javascript 存储过程 运行 在一个集合中,不能 access/reference 另一个集合中的数据。
如果上述情况属实,那么我们的应用程序数据源以关系方式设计的数据源位于何处?如果业务需要立即查询,收集以下数据: 所有 agreements/contracts 已在给定时间范围内迁移到特定区域内的新产品。如果大约有 5 个集合包含与此查询相关的所有信息,我将如何处理此查询?
有指导吗?
更新
客户
{
"id": "d02e6668-ce24-455d-b241-32835bb2dcb5",
"Name": "Test User One",
"Surname": "Test"
}
协议
{
"id": "ee1094bd-16f4-45ec-9f5e-7ecd91d4e729",
"CustomerId": "d02e6668-ce24-455d-b241-32835bb2dcb5"
"RetailProductVersionInstance":
[
{
"id": "8ce31e7c-7b1a-4221-89a3-449ae4fd6622",
"RetailProductVersionId": "ce7a44a4-7e49-434b-8a51-840599fbbfbb",
"AgreementInstanceUser": {
"FirstName": "Luke",
"LastName": "Pothier",
"AgreementUserTypeId": ""
},
"AgreementInstanceMSISDN": {
"IsoCountryDialingCode": null,
"PhoneNumber": "0839263922",
"NetworkOperatorId": "30303728-9983-47f9-a494-1de853d66254"
},
"RetailProductVersionInstanceState": "IN USE",
"IsPrimaryRetailProduct": true,
"RetailProductVersionInstancePhysicalItems": [
{
"id": "f8090aba-f06b-4233-9f9e-eb2567a20afe",
"PhysicalItemId": "75f64ab3-81d2-f600-6acb-d37da216846f",
"RetailProductVersionInstancePhysicalItemNumbers": [
{
"id": "9905058b-8369-4a64-b9a5-e17e28750fba",
"PhysicalItemNumberTypeId": "39226b5a-429b-4634-bbce-2213974e5bab",
"PhysicalItemNumberValue": "KJDS959405"
},
{
"id": "1fe09dd2-fb8a-49b3-99e6-8c51df10adb1",
"PhysicalItemNumberTypeId": "960a1750-64be-4333-9a7f-c8da419d670a",
"PhysicalItemNumberValue": "DJDJ94943"
}
],
"RetailProductVersionInstancePhysicalItemState": "IN USE",
"DateCreatedUtc": "2018-11-21T13:55:00Z",
"DateUpdatedUtc": "2020-11-21T13:55:00Z"
}
]
}
]
}
RetailProduct
{
"id": "ce7a44a4-7e49-434b-8a51-840599fbbfbb",
"FriendlyName": "Data-Package 100GB",
"WholeSaleProductId": "d054dae5-173d-478b-bb0e-7516e6a24476"
}
批发产品:
{
"id": "d054dae5-173d-478b-bb0e-7516e6a24476",
"ProductName": "Data 100",
"ProviderLiabilities": []
}
上面,我添加了一些示例文档。
关系:
- Agreement.CustomerId 链接到 Customer.id
- Agreement.RetailProductVersionInstance.RetailProductVersionId 个链接 至 RetailProduct.id
- RetailProduct.WholeSaleProductId 链接到 WholeSaleProduct.id
我如何在 CosmosDB 中编写 Javascript 存储过程来执行这 4 个集合之间的连接?
简而言之,您不能通过 Cosmos DB 中的 SQL 在不同集合之间执行连接。
一般来说,这类问题的解决方案是多次查询或者不同的schema。在您的场景中,如果您可以在不复制数据的情况下将架构反规范化为一个集合,那么这很容易。
如果您提供架构,则可能会提供更全面的答案。
-- 编辑 1 --
存储过程仅适用于需要对同一集合 + 分区键执行多项操作的操作。这使得它们非常适合批量 insert/delete/update、事务(至少需要一次读取和一次写入)以及其他一些事情。它们不适用于 CPU 密集型事物,而是通常受网络延迟限制的 IO 事物。它们不可能用于跨分区或跨集合场景。在这些情况下,您必须专门从远程客户端执行操作。
对于您的情况,这是相当简单的 2 + 2N
单独读取,其中 N
是产品数量。您需要先阅读协议。然后你可以并行查找客户和产品记录,然后你可以最后查找批发记录,所以你应该有 3s + C
的延迟,其中 s
是平均持续时间给定读取请求并且 C
是某个常量 CPU 执行 join/issue 和 request/etc.
值得考虑的是,您是否可以将 RetailProduct 和 WholeSale 产品合并到单个记录中,其中 Wholesale 包含数组中的所有 RetailProducts,或者作为单独的文档,按批发 ID 分区,具有包含 Wholesale 的众所周知的 ID单独文档中的产品信息。这将使您的延迟减少三分之一。如果您采用按批发 ID 进行分区的想法,您可以为共享批发 ID 的任何记录编写 1 个查询,这样您将获得 2 + log(N)
次读取,但有效延迟相同。对于该策略,您将在协议中存储 "wholesaleid+productid" 的复合索引。一个值得担心的问题是它复制了批发+产品关系,但只要这种关系不改变,我认为没有什么可担心的,它为信息查找提供了很好的优化。