azure - CosmosDB 存储过程不返回所有文档

标签 azure stored-procedures azure-storage azure-cosmosdb

我有一个非常简单的存储过程,它向许多文档返回 0。这是代码:

function GetAllDocuments(numberOfDays){

  var context = getContext();
  var response = context.getResponse();
  var collection = context.getCollection();
  var collectionLink = collection.getSelfLink();

  var today  = new Date();  
  today.setDate(today.getDate() - numberOfDays);
  var inSeconds = today.getTime() / 1000; 
  var filterQuery = 'SELECT * FROM c WHERE c._ts >' + inSeconds;

  console.log(filterQuery);
  collection.queryDocuments(collectionLink, filterQuery, {pageSize:-1},
    function(err, documents) {
      response.setBody(response.getBody() + JSON.stringify(documents));
    }
  );
}

我面临的问题是,如果有很多文件要返回,即20000,则并非所有文件都会返回。我想我遇到了需要传递 continuationToken 的问题。我读过其他文章,其中指出我们需要返回客户端(c#),然后再次调用传递 token 的存储过程。我还没有找到代码示例。这也是确保全额返回的唯一方法吗?这只是一个存储过程问题吗?我是否最好只使用 client.CreateDocumentQuery 来简单地在一次调用中返回所有记录?

感谢您的反馈!

这是使用 Jay 示例的新代码:

function GetAllDocumentsNew(numberOfDays) {

       var collection = getContext().getCollection();
       var collectionLink = collection.getSelfLink();
       var response = getContext().getResponse();
       var docCount = 0;
       var counter = 0;
       var returnArray = [];

       var today  = new Date();  
       today.setDate(today.getDate() - numberOfDays);
       var inSeconds = today.getTime() / 1000; 
       //var filterQuery = 'SELECT * FROM c WHERE c._ts >' + inSeconds;
       var filterQuery = "select * from c where c._ts > 1531763849.225 and c._ts <1532637743.261 and c.ProcessTypeID = 1";

       console.log(filterQuery);

       tryQuery();

       function tryQuery(continuation) {
            var query = {
                query: filterQuery
            };

            var requestOptions = {
                MaxItemCount: 10000,
                continuation: continuation
            };

            var isAccepted =
                collection
                .queryDocuments(collectionLink,
                                query,
                                requestOptions,
                                function queryCallback(err, documents,responseOptions) {
                                         if (err) throw err;
                                         if (documents.length > 0) {

                                            docCount = documents.length;
                                            console.log(docCount.toString());
                                            for (var i=0; i<docCount; i++){
                                                returnArray.push(documents[i]);
                                            }

                                           getContext().getResponse().setBody(returnArray);
                                          }
                                          else if (responseOptions.continuation) {
                                              // Else if the query came back empty, but with a continuation token; 
                                              // repeat the query with the token.
                                            tryQuery(responseOptions.continuation);
                                          } else {
                                                 throw new Error("Document not found.");
                                                 }
                                });

            if (!isAccepted) {
                throw new Error("The stored procedure timed out");
            }
        }
    }

最佳答案

if there are many documents to be returned ie 20000 not all documents are returned. I think i am running into the issue where i need to pass a continuationToken.

当查询数据相当庞大时,当然需要考虑在存储过程中使用延续 token 。您可以引用如下伪代码:

function GetAllDocuments(numberOfDays) {

       var collection = getContext().getCollection();
       var collectionLink = collection.getSelfLink();
       var response = getContext().getResponse();
       var docCount = 0;
       var counter = 0;
       var returnArray = [];

       var today  = new Date();  
       today.setDate(today.getDate() - numberOfDays);
       var inSeconds = today.getTime() / 1000; 
       var filterQuery = 'SELECT * FROM c WHERE c._ts >' + inSeconds;

       tryQuery();

       function tryQuery(continuation) {
            var query = {
                query: "select * from root r"
            };

            var requestOptions = {
                MaxItemCount: 1000
                continuation: continuation
            };

            var isAccepted =
                collection
                .queryDocuments(collectionLink,
                                query,
                                requestOptions,
                                function queryCallback(err, documents,responseOptions) {
                                         if (err) throw err;
                                         if (documents.length > 0) {

                                            docCount = documents.length;
                                            for (var i=0; i<docCount; i++){
                                                returnArray.push(documents[i]);
                                            }

                                           getContext().getResponse().setBody(returnArray);
                                          }
                                          else if (responseOptions.continuation) {
                                              // Else if the query came back empty, but with a continuation token; 
                                              // repeat the query with the token.
                                            tryQuery(responseOptions.continuation);
                                          } else {
                                                 throw new Error("Document not found.");
                                                 }
                                });

            if (!isAccepted) {
                throw new Error("The stored procedure timed out");
            }
        }
    }

I have read other posts that states that we will need to return to client(c#) then make another call to the sproc passing in a token. I havent been able to find a code sample.

据我所知,存储过程有5秒的运行限制( Is it possible to disable the 5 second time limit for Azure CosmosDB stored procedures ,如果您的存储过程超时,则需要调用[ExecuteStoredProcedureAsync][1]在您的客户端并将继续 token 作为参数传递。

Will i be better off to just use client.CreateDocumentQuery that will simply return all records in one call?

据我所知,存储过程是在服务器端运行的JS代码脚本。我认为性能比使用客户端调用SDK更有效。但受限于JS语法和运行时间。如果您不能容忍这些功能,我建议您可以通过客户端SDK来完成您的需求。

希望对您有帮助。如有任何疑问,请告诉我。

关于azure - CosmosDB 存储过程不返回所有文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51601158/

相关文章:

c# - 通过应用程序洞察中的端到端事务跟踪 azure redis

MySQL 存储过程 if 语句不工作

mysql - 我的mysql功能不起作用?

azure - Azure存储帐户说明-总请求图表

当新消息进入服务总线队列时,Azure 函数(服务总线触发器)无法启动

Azure DevOps,如何在 DevOps 待办事项中添加 "Work Item type"

c# - 删除 Azure Keyvault 上的 secret 不起作用

sql - 如何从另一个存储过程调用一个存储过程?

Azure模拟器端口冲突,应用程序尝试连接到错误的端口

angular - 循环上传文件不起作用