CosmosDB存储过程未返回所有文档

时间:2018-07-30 19:40:25

标签: 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的问题。我读过其他文章,指出我们需要返回到client(c#),然后再次调用传递令牌的sproc。我还没有找到代码示例。这也是确保全额回报的唯一方法吗?仅仅是存储过程问题吗?仅使用client.CreateDocumentQuery会在一次调用中返回所有记录的情况会更好吗?

感谢您的反馈!

这是使用杰伊的示例的新代码:

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");
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

  

如果要返回的文档很多,即20000并非所有文档   返回。我认为我遇到了我需要通过的问题   一个continuationToken。

当查询数据很大时,当然,您需要考虑在存储过程中使用延续令牌。您可以参考以下伪代码:

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");
            }
        }
    }
  

我还阅读了其他文章,指出我们需要返回至   然后client(c#)再次调用传递令牌的sproc。一世   还没有找到代码示例。

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

  

我会更好地只使用client.CreateDocumentQuery   只需一次调用即可返回所有记录?

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

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