从(SELECT DISTINCT c.UserId from root c)中选择值计数(1)

时间:2019-07-18 01:25:01

标签: azure azure-cosmosdb azure-cosmosdb-sqlapi

在Cosmos DB存储过程中,我使用内联sql查询来尝试检索特定用户ID的不重复计数。

我正在为我的帐户使用SQL API。我已经在Cosmos DB帐户的Query Explorer中运行了以下查询,并且我知道应该得到10(我的集合中有10个唯一的用户ID):

SELECT VALUE COUNT(1) FROM (SELECT DISTINCT c.UserId FROM root c) AS t

但是,当我在“存储过程”门户网站中运行此命令时,我要么得到0条记录,要么得到18条记录(文档总数)。我的存储过程的代码如下:

function GetDistinctCount() {
    var collection = getContext().getCollection();

    var isAccepted = collection.queryDocuments(
        collection.getSelfLink(),
        'SELECT VALUE COUNT(1) FROM (SELECT DISTINCT c.UserId  FROM root c) AS t',      
        function(err, feed, options) {
            if (err) throw err;

            if (!feed || !feed.length) {
                var response = getContext().getResponse();
                var body = {code: 404, body: "no docs found"}
                response.setBody(JSON.stringify(body));
            } else {
                var response = getContext().getResponse();
                var body = {code: 200, body: feed[0]}
                response.setBody(JSON.stringify(body));
            }
        }
    )
}

在查看了各种反馈论坛和文档之后,我认为没有一个像普通SQL那样简单的优雅解决方案。

用户ID是我的分区键,我在C#代码中以及在门户中对其进行测试时会通过该键,因此在调用Stored Proc时不需要设置其他参数。我正在通过C#调用此存储过程,并添加任何其他参数将对该代码的测试产生影响,因此,我尽可能不引入任何参数。

2 个答案:

答案 0 :(得分:0)

您的问题是由于您没有为存储过程设置分区键而引起的。

请参见官方document中的声明:

enter image description here

这:

enter image description here

因此,当您在分区集合下执行存储过程时,需要传递分区键参数。这是必要的! (此案例也对此进行了解释:Documentdb stored proc cross partition query

回到您的问题,您永远不会传递任何分区键,就等于您传递了分区键的null值或""值,因此它不输出任何数据,因为您没有任何userId等于null或“”。

enter image description here

我的建议: 您可以使用普通的Query SDK来执行您的sql,并设置enableCrossPartitionQuery: true,以使您无需设置分区键即可扫描整个集合。请参考这个小样本:Can't get simple CosmosDB query to work via Node.js - but works fine via Azure's Query Explorer

答案 1 :(得分:0)

因此,我找到了一个返回所需结果的解决方案。我的存储过程现在看起来像这样:

function GetPaymentCount() {
    var collection = getContext().getCollection();

    var isAccepted = collection.queryDocuments(
        collection.getSelfLink(),
        'SELECT DISTINCT VALUE(doc.UserId) from root doc' ,
        {pageSize:-1 },

        function(err, feed, options) {
            if (err) throw err;

            if (!feed || !feed.length) {
                var response = getContext().getResponse();
                var body = {code: 404, body: "no docs found"}
                response.setBody(JSON.stringify(body));
            } else {
                var response = getContext().getResponse();
                var body = {code: 200, body: JSON.stringify(feed.length)}
                response.setBody(JSON.stringify(body));
            }
        }
    )
}

本质上,我将pageSize参数更改为-1,该参数返回了我知道会在结果中返回的所有文档。我有一种感觉,就RU / s的成本而言,这将更加昂贵,但现在可以解决我的情况。

如果有人有更有效的替代方法,请发表评论并让我知道。