第一个文档db不支持count(),它们提供了stored procedure来获取我在下面的存储过程中使用的计数
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,有时总计)。它工作正常结果的数量少于另一个集合。我尝试将两个程序分开但仍然相同。
答案 0 :(得分:0)
存储过程超过某些限制(至少是时间)时会被强行终止。这就是为什么您链接到的原始示例返回了正文中的延续令牌的原因。您上面的版本已删除,但您需要将其恢复。这样,如果从第一次调用存储过程返回的结果包含一个延续令牌,您就知道再次调用它。最终计数将是对存储过程的所有调用的总和。
您可能还想将maxResult降低到1000或10,000。这样可以提供更精细的粒度,根据我的经验,实际上得到的答案比拥有非常大的数字更快。
我并不是编写示例计数存储过程的方式的忠实粉丝。 Here是我的等同物。主要区别在于它返回的对象的形状与它接受的形状相同,并且每次都来回传递重新启动已终止的存储过程所需的所有状态。我已经写过关于编写存储过程here的这种方法。 documentdb-utils(这些链接所在的位置)包含Azure提供的node.js SDK的包装器,它将自动保持调用过早终止的存储过程,直到它们实际完成为止。完全披露,我是documentdb-utils的作者。
答案 1 :(得分:0)
您还可以查看我在Omex Document DB Github存储库中编写的Count存储过程: https://github.com/microsoft/Omex/blob/master/src/DocumentDb/Scripts/Count.js