2017-02-15 21 views
0

头文件DB不提供对数()的支持,他们提供了一个stored procedure让我在我的存储过程使用了下面获取用于计数不同的结果在documentdb

function usp_GetInfinityDataView(param) { 
    var context = getContext(); 
    var response = context.getResponse(); 
    var collection = context.getCollection(); 
    var collectionLink = collection.getSelfLink(); 
    var Rount = 0; 
    count("SELECT i.id FROM infinity i",null); 

    var query = { 
    query: 'SELECT * FROM infinity i' 
    }; 

    getNodes(param["ContinuationToken"],param["PageSize"]); 

    function getNodes(continuationToken,intPageSize) { 
    // Tune the pageSize to fit your dataset. 
    var requestOptions = { 
     continuation: continuationToken, 
     pageSize: intPageSize 
    }; 

    var accepted = collection.queryDocuments(collectionLink, query, requestOptions, 
     function(err, documentsRead, responseOptions) { 
     response.setBody({ 
       "ResponseContinuation": responseOptions.continuation, 
       "Count": Rount, 
       "ViewData": documentsRead 
      }); 
     }); 
    } 

    function count(filterQuery, continuationToken) { 
    var collection = getContext().getCollection(); 
    var maxResult = 99999999999; // MAX number of docs to process in one batch, when reached, return to client/request continuation. 
         // intentionally set low to demonstrate the concept. This can be much higher. Try experimenting. 
         // We've had it in to the high thousands before seeing the stored proceudre timing out. 

    // The number of documents counted. 
    var result = 0; 

    tryQuery(continuationToken); 

    // Helper method to check for max result and call query. 
    function tryQuery(nextContinuationToken) { 
     var responseOptions = { continuation: nextContinuationToken, pageSize : maxResult }; 

     // In case the server is running this script for long time/near timeout, it would return false, 
     // in this case we set the response to current continuation token, 
     // and the client will run this script again starting from this continuation. 
     // When the client calls this script 1st time, is passes empty continuation token. 
     if (result >= maxResult || !query(responseOptions)) { 
      setBody(nextContinuationToken); 
     } 
    } 

    function query(responseOptions) { 
     // For empty query string, use readDocuments rather than queryDocuments -- it's faster as doesn't need to process the query. 
     return (filterQuery && filterQuery.length) ? 
      collection.queryDocuments(collection.getSelfLink(), filterQuery, responseOptions, onReadDocuments) : 
      collection.readDocuments(collection.getSelfLink(), responseOptions, onReadDocuments); 
    } 

    // This is callback is called from collection.queryDocuments/readDocuments. 
    function onReadDocuments(err, docFeed, responseOptions) { 
     if (err) { 
      throw 'Error while reading document: ' + err; 
     } 

     // Increament the number of documents counted so far. 
     result += docFeed.length; 

     // If there is continuation, call query again with it, 
     // otherwise we are done, in which case set continuation to null. 
     if (responseOptions.continuation) { 
      tryQuery(responseOptions.continuation); 
     } else { 
      setBody(null); 
     } 
    } 

    // Set response body: use an object the client is expecting (2 properties: result and continuationToken). 
    function setBody(continuationToken) { 
     Rount = result; 
    } 
} 
} 

的问题是计数每次我从c#web api调用这个过程时,它给了我不同的结果,而不是实际的计数(就像我的结果集计数为17491,但是返回17020或17202,有时也返回总计)。当结果数量少时,它可以正常工作即在另一个collection.I试图分离两个程序,但仍然是相同的。

回答

0

存储过程在超过某个限制(至少时间)时被强制终止。这就是为什么您链接的原始示例返回正文中的延续标记的原因。您上面的版本已删除,但您需要恢复它。这样,如果从第一次调用存储过程返回的结果包含连续标记,则需要再次调用它。最终计数将是对存储过程的所有调用的总和。

您可能还想将maxResult降低回1000或10,000。这给你提供了更精细的粒度,并且根据我的经验,实际上得到的答案比拥有非常大的数字更快。

我不是示例计数存储过程写入方式的巨大粉丝。 Here是我的等价物。主要区别在于它返回的对象的形状与其接受的形状相同,并且每次重新启动已终止的存储过程所需的所有状态都会前后传递。我已经写过关于编写存储过程的方法here。 documentdb-utils(这些链接去的地方)包含Azure提供的node.js SDK的包装器,它将自动保持调用过早终止的存储过程直到它们实际完成。充分披露,我是documentdb-utils的作者。