0
votes

I have at around 70,000 documents in cosmos db collection. I am using following stored procedure to delete items(documents) in bulk.

But when I am executing this stored procedure it is deleted only 500 documents. How Can I delete all items(documents) in one shot?

This is my delete query:

SELECT COUNT(1) FROM c WHERE c.UserUUId=null

Stored Procedure:

function bulkDeleteSproc(query) {
    var collection = getContext().getCollection();
    var collectionLink = collection.getSelfLink();
    var response = getContext().getResponse();
    var responseBody = {
        deleted: 0,
        continuation: true
    };

    // Validate input.
    if (!query) throw new Error("The query is undefined or null.");

    tryQueryAndDelete();

    // Recursively runs the query w/ support for continuation tokens.
    // Calls tryDelete(documents) as soon as the query returns documents.
    function tryQueryAndDelete(continuation) {
        var requestOptions = {continuation: continuation};

        var isAccepted = collection.queryDocuments(collectionLink, query, requestOptions, function (err, retrievedDocs, responseOptions) {
            if (err) throw err;

            if (retrievedDocs.length > 0) {
                // Begin deleting documents as soon as documents are returned form the query results.
                // tryDelete() resumes querying after deleting; no need to page through continuation tokens.
                //  - this is to prioritize writes over reads given timeout constraints.
                tryDelete(retrievedDocs);
            } else if (responseOptions.continuation) {
                // Else if the query came back empty, but with a continuation token; repeat the query w/ the token.
                tryQueryAndDelete(responseOptions.continuation);
            } else {
                // Else if there are no more documents and no continuation token - we are finished deleting documents.
                responseBody.continuation = false;
                response.setBody(responseBody);
            }
        });

        // If we hit execution bounds - return continuation: true.
        if (!isAccepted) {
            response.setBody(responseBody);
        }
    }

    // Recursively deletes documents passed in as an array argument.
    // Attempts to query for more on empty array.
    function tryDelete(documents) {
        if (documents.length > 0) {
            // Delete the first document in the array.
            var isAccepted = collection.deleteDocument(documents[0]._self, {}, function (err, responseOptions) {
                if (err) throw err;

                responseBody.deleted++;
                documents.shift();
                // Delete the next document in the array.
                tryDelete(documents);
            });

            // If we hit execution bounds - return continuation: true.
            if (!isAccepted) {
                response.setBody(responseBody);
            }
        } else {
            // If the document array is empty, query for more documents.
            tryQueryAndDelete();
        }
    }
}

Here is the output after executing the store procedure:

enter image description here

2

2 Answers

2
votes

Stored procedures are scoped to execute in a single logical partition. So you must pass the partition key value for each execution of your stored procedure. To do this you will need to run one cross partition query to get a distinct on your partition key path. then loop through that result set and call your stored procedure with each partition key value.

I should note that if you are attempting to delete every value in your collection it is far less expensive to delete the collection itself and then recreate it.

Hope that helps.

1
votes

As noted by Mark, it might be less expensive to delete the collection itself instead of individual items.

If for some reason, you would want to delete the items rather than the entire collection, you may consider using TTL settings. Refer to https://docs.microsoft.com/en-us/azure/cosmos-db/time-to-live

TTL can be set at container level as well as item level. Also, since TTL expiry of items use surplus RUs, they are less expensive

Hope this helps