【发布时间】:2021-08-27 01:27:09
【问题描述】:
考虑一个具有以下文档模型的 CosmosDB 容器:
{
id: <string>,
userId: <string>, // partition key
data: <string>
}
我需要提供一个包含 N 个用户 ID 的查询并获取每个用户 ID 的最新文档。
例如,如果我在容器中有这些数据:
{ id: '1', userId: 'user1', data: 'a', _ts: 1 },
{ id: '2', userId: 'user1', data: 'b', _ts: 2 },
{ id: '3', userId: 'user2', data: 'c', _ts: 10 },
{ id: '4', userId: 'user2', data: 'd', _ts: 5 },
{ id: '5', userId: 'user3', data: 'e', _ts: 3 },
{ id: '6', userId: 'user3', data: 'f', _ts: 4 },
{ id: '7', userId: 'user4', data: 'g', _ts: 100 },
{ id: '8', userId: 'user4', data: 'h', _ts: 99 },
{ id: '9', userId: 'user5', data: 'i', _ts: 1 },
{ id: '10', userId: 'user5', data: 'j', _ts: 2 },
我想做这样的事情:
-- This doesn't work
SELECT c.userId, (SELECT TOP 1 d.id, d.data WHERE d.userId = c.userId FROM d ORDER BY d._ts DESC) AS newest
WHERE c.userId IN ['user1', 'user2', 'user4', 'user5']
要得到这个结果:
{ userId: 'user1', newest: { id: '2', data: 'b' } },
{ userId: 'user2', newest: { id: '3', data: 'c' } },
{ userId: 'user4', newest: { id: '7', data: 'g' } },
{ userId: 'user5', newest: { id: '10', data: 'j' } },
据我所知,CosmosDB 中的 JOIN 不能用于过滤相关文档。还有办法做到这一点吗?我愿意使用存储过程,但据我所知,存储过程的执行只能在特定分区上发生,因为它是关键。在我的例子中,主要分组是分区键。
我考虑过扇出请求方法,但我可能在查询中一次查询 50 到 100 个用户 ID。在这种情况下,只获取每个分区中的所有文档并在迭代时只保留最新的文档可能会更快——但这是一个需要筛选的大页面响应。
我最后的想法是,我可以使用 ASB/EventGrid/Function 和另一个依赖的 CosmosDB 容器来始终在每次更新文档时克隆最新更新的文档,但这似乎有点矫枉过正。肯定有一种方法可以构造一个查询来做我想做的事吗?
谢谢
【问题讨论】:
-
select value max(c._ts) from c group by c.userId可以得到每个用户最新列的时间戳列表。 -
即使有办法,这也可能是一个昂贵的查询。我的直觉是使用更改提要将用户的最新项目保存在单独的容器中以优化读取。
标签: azure-cosmosdb greatest-n-per-group azure-cosmosdb-sqlapi