我有一个存储过程,它给我一个文档计数(count.js on github)。我已经分区了我的收藏。因此,我现在必须传递分区键作为运行存储过程的选项。
可以以及如何在存储过程中启用跨分区查询(即collection(EnableCrossPartitionQuery = true)
),以便我不必指定分区键?
答案 0 :(得分:2)
无法在DocumentDB中执行扇出存储过程。针对单个分区运行。在尝试切换到分区集合时我遇到了这种困境,不得不进行一些调整。以下是一些选项:
为每条记录下载1,并将它们计入客户端
为每个唯一的分区键重新运行存储过程。在我的情况下,这并没有它听起来那么糟糕,因为分区键是一个tenantID,我只有十几个,只期望最多几百个。
我不确定这个,因为我没有尝试使用分区集合,但现在每个查询都返回x-ms-resource-usage标头中集合的资源使用情况。该标头有一个documentsSize子标头。您可以使用除以文档平均大小的值来获得近似计数。到目前为止,该标题信息中甚至可能存在计数记录。
此外,还有一个x-ms-item-count标头,但我不确定它是如何表现的。如果您对整个分区集合中的所有记录发送查询并将max-item-count设置为1,那么您将只返回一条记录,并且它不应该花费您很多RU,但我不会知道那个标题是如何表现的。在这种情况下它会返回1吗?或者如果您打扰请求每个页面,它是否返回查询的所有页面最终将返回的文档总数。快速实验应该证实这一点。
答案 1 :(得分:0)
下面您可以找到一些示例代码,这些代码应允许您跨分区读取所有记录。神奇之处在于doForAll
函数内部,您可以在顶部看到其调用方式。
// SAMPLE STORED PROCEDURE
function sample(prefix) {
var share = { counter: 0, hasEntityName : 0, isXXX: 0, partitions: {}, prefix };
doForAll({
filter: function limiter(record){
if (record && record.entityName === 'XXX') return true;
else return false;
},
callback: function handleRecord(record) {
//Keep track of this partition...
let partitionKey = record.partitionKey;
if (share.partitions[partitionKey])
share.partitions[partitionKey]++;
else
share.partitions[partitionKey] = 1;
//update some counters...
share.counter++;
if (record.entityName !== undefined) share.hasEntityName++;
if (record.entityName === 'XXX') share.isXXX++;
},
finaly: function whenAllIsDone() {
console.log("counter = " + share.counter + ". ");
console.log("has entity name: "+ share.hasEntityName+ ". ")
console.log("is XXX: " + share.isXXX+ ". ")
var parts = Object.getOwnPropertyNames(share.partitions)
console.log("partition keys: " + parts.length + " ...");
getContext()
.getResponse()
.setBody(share);
}
});
//The magic function...
//also see: https://azure.github.io/azure-cosmosdb-js-server/Collection.html
function doForAll(task, ctoken) {
if (!task) throw "Expected one parameter of type: { filter?: (rec?)=>boolean, callback?: (rec?) => void, finaly?: () => void }";
//Note:
//the "__" symbol is an alias for var collection = getContext().getCollection(); = aliased by __
var result = getContext()
.getCollection()
.chain()
.filter(task.filter || function (rec) { return true; })
.map(task.callback || function (rec) { return undefined; })
.value({ continuation: ctoken }, function afterBatchCallback (err, feed, options) {
if (err) throw err;
if (options.continuation)
doForAll(task, options.continuation);
else if (task.finaly)
task.finaly();
});
if (!result.isAccepted)
throw "catastrophic failure";
}
}
PS:它可能知道该示例使用的数据看起来如何。 这是此类文档的示例:
{
"id": "123",
"partitionKey": "PART_1",
"entityName": "EXAMPLE_ENTITY",
"veryInterestingInfo": "The 'id' property is also the collections id, the 'partitionKey' property happens to be the collections partition key, and all the records in this collection have a 'entityName' property which contains a (non-unique) string"
}