Хранимая процедура для обновления или вставки документов, которые принадлежат нескольким ключам разделов - PullRequest
0 голосов
/ 14 мая 2018

У меня есть список документов, которые относятся к многораздельной коллекции.Вместо того, чтобы запрашивать каждый документ из клиента .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 ]

0 голосов
/ 14 мая 2018

По звуку, ваш уникальный идентификатор представляет собой комбинацию code и type. Я бы порекомендовал сделать вашу собственность id комбинацией двух.

Это гарантирует, что ваш id уникален, но также устраняет необходимость запрашивать его.

0 голосов
/ 14 мая 2018

Если коллекция, против которой зарегистрирована хранимая процедура, является однораздельный сбор, то транзакция распространяется на все документы в коллекции. Если коллекция разделена, затем хранимые процедуры выполняются в объеме транзакции один раздел ключа. Каждое выполнение хранимой процедуры должно затем включить значение ключа раздела, соответствующее области действия транзакция должна выполняться под.

Вы можете обратиться к описанию выше, в котором упоминается здесь . Мы можем запросить документы между разделами, установив EnableCrossPartitionQuery в true в параметре FeedOptions. Однако RequestOptions не имеет таких свойств по отношению к выполнению хранимой процедуры.

Итак, похоже, что вы должны предоставить ключ раздела при запуске sp. Конечно, его можно заменить функцией upsert. Это бесполезно с точки зрения бизнес-логики, но если массовые операции, SP может снять некоторое давление производительности, потому что SP работает на стороне сервера.

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...