我有一个类似于
"id": "uuid",
"deviceId": "uuid",
"message": {
"content": "string",
"ts": 1
},
"data": {
"temperature": 21
}
我想得到每个"deviceId".的最新“数据”(使用message.ts作为时间戳)。
到目前为止,我已经按照使用查询SELECT c.deviceId, c.message.ts, c.data FROM c ORDER BY c.message.ts DESC
的时间戳顺序,设法将数据取回,但我不知道如何删除重复的设备记录。
在CosmosDB SQL引擎中可以这样做吗?
发布于 2020-11-09 03:40:46
多亏了Mark Brown的评论,我发现下面这个问题似乎是正确的解决方案,不像一次性使用一些SQL那样优雅,而是真正需要的。
本质上,您创建了一个由Cosmos变更提要触发的Serverless函数,并更新了一个物化视图,这个视图本质上只是一个文档,其中包含(在本例中)每个deviceId
中最最新的deviceId
。
特别是在这种情况下,它很可能用最新的数据更新相应的device
文档。
发布于 2021-02-19 12:07:18
您可以采取的另一种方法是在CosmosDb中使用触发器函数。这样做的好处是您不需要部署Azure函数,只需使用SQL获取最新的项。例如,当您获得一个新项时,您可以使用预触发器设置一个字段,如下所示:latest = true
,同时将前一项的最新字段更改为false。然后,您的SQL查询将只需要WHERE latest = true
来返回每一项的最新记录。下面是一个具有一般思想的触发器函数:
function setLatest() {
var context = getContext();
var request = context.getRequest();
// item to be created in the current operation
var itemToCreate = request.getBody();
// validate properties
if (!("latest" in itemToCreate)) {
itemToCreate["latest"] = true;
}
// update the old latest to false
removeCurrentLatest(itemToCreate["id"],..., );
// save the newer item that will be created
request.setBody(itemToCreate);
}
function removeCurrentLatest(id, ...) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
// Get the document. We keep it in the same collection.
var isAccepted = collection.queryDocuments
(collectionLink, `SELECT * FROM root r WHERE r.id = "${id}" AND .... AND r.latest = true`,
function (err, feed, options) {
if (err) throw err;
if (feed && feed[0] != null)
{
var oldDoc = feed[0];
oldDoc.latest = false;
var isAccepted = collection.replaceDocument(oldDoc._self, oldDoc, function (err) {
if (err) throw err;
});
if (!isAccepted) throw new Error("The call replaceDocument(oldDoc) returned false.");
}
});
if (!isAccepted) throw new Error("The call queryDocuments for oldDoc returned false.");
}
我删除了一些其他条件,您可能需要包括以确保您选择了正确的前一个版本的项目-希望这应该是显而易见的,如何为您的特定资产添加这些条件。这是一篇关于在CosmosDB:http://www.johndowns.co.nz/blog/2018/1/30/cosmos-db-server-side-programming-with-typescript-part-4-triggers中使用触发器的优秀文章。
发布于 2020-11-09 01:39:03
到目前为止,用一个SQL实现这一点是不可能的。
也许这是另一种选择。
首先,运行这个SQL SELECT c.deviceId,max(c.message.ts) as lastest FROM c group by c.deviceId
。
然后,您可以通过这个SQL,SELECT * FROM c WHERE c.deviceId = 'xxx' AND c.message.ts = xxxx
获得数据。
https://stackoverflow.com/questions/64712120
复制