我有一个属于分区集合的文档列表 . 不是从.NET客户端查询每个文档,而是更新或插入,我想我可以使用存储过程来完成此任务 .
我最初没有意识到存储过程是在单个分区键的事务范围内执行的 . 所以我得到 PartitionKey value must be supplied for this operation
.
问题是文件(我试图插入)可能属于不同的分区 . 如何在存储过程中完成此操作?就我而言,SP是无用的,除非它可以在多个分区上运行 .
这就是我构建SP的方式:
function upsertEcertAssignments(ecerts) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var response = getContext().getResponse();
// Validate input
if (!ecerts) throw new Error("The ecerts is null or undefined");
if (ecerts.length == 0) throw new Error("The ecerts list size is 0");
// Recursively call the 'process' function
processEcerts(ecerts, 0);
function processEcerts(ecerts, index) {
if (index >= ecerts.length) {
response.setBody(index);
return;
}
var query = {query: "SELECT * FROM DigitalEcerts c WHERE c.code = @code AND c.collectionType = @type", parameters: [{name: "@code", value: ecerts[index].code}, {name: "@type", value: 0}]};
var isQueryAccepted = collection.queryDocuments(collectionLink, query, {partitionKey: ecerts[index].code}, function(err, foundDocuments, foundOptions) {
if (err) throw err;
if (foundDocuments.length > 0) {
var existingEcert = foundDocuments[0];
ecerts[index].id = existingEcert.id;
var isAccepted = __.replaceDocument(existingEcert._self, ecerts[index], function(err, updatedEcert, replacedOptions) {
if (err) throw err;
processEcerts(ecerts, index + 1);
});
if (!isAccepted) {
response.setBody(index);
}
} else {
var isAccepted = __.createDocument(__.getSelfLink(), ecerts[index], function(err, insertedEcert, insertedOptions) {
if (err) throw err;
processEcerts(ecerts, index + 1);
});
if (!isAccepted) {
response.setBody(index);
}
}
});
if (!isQueryAccepted)
response.setBody(index);
}
}
从.NET,如果我这样称呼它,我得到partitionKey值问题:
var continuationIndex = await _docDbClient.ExecuteStoredProcedureAsync<int>(UriFactory.CreateStoredProcedureUri(_docDbDatabaseName, _docDbDigitalEcertsCollectionName, "UpsertDigitalMembershipEcertAssignments"), digitalEcerts);
如果我用分区键调用它,它可以工作......但它没用:
var continuationIndex = await _docDbClient.ExecuteStoredProcedureAsync<int>(UriFactory.CreateStoredProcedureUri(_docDbDatabaseName, _docDbDigitalEcertsCollectionName, "UpsertDigitalMembershipEcertAssignments"), new RequestOptions { PartitionKey = new PartitionKey(digitalEcerts[0].Code) }, digitalEcerts.Take(1).ToList());
我很欣赏任何指针 .
谢谢 .
2 回答
根据它的声音,您的唯一ID是
code
和type
的组合 . 我建议你将id
属性作为两者的组合 .这可以保证
id
是唯一的,但也无需查询它 .你可以参考上面提到here的描述 . 我们可以通过在
FeedOptions
参数中将EnableCrossPartitionQuery
设置为true
来查询文档跨分区 . 但是,RequestOptions
没有执行存储过程的此类属性 .所以,执行sp时似乎必须提供分区键 . 当然,它可以用upsert函数代替 . 从业务逻辑的角度来看它是无用的,但是如果是批量操作,SP可以释放一些性能压力,因为SP在服务器端运行 .
希望它能帮到你 .