首页 > 解决方案 > 如何使用 SQL 获取 CosmosDB 中每个项目的最新记录

问题描述

我有一个类似于

"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 引擎中完成吗?

标签: sqlazure-cosmosdbazure-cosmosdb-sqlapi

解决方案


您可以采取的另一条路线是在 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


推荐阅读