关于 azure cosmosdb:为什么 Cosmos 存储过程在从浏览器调用与从 Java 调用时运行方式不同?

Why would a Cosmos stored procedure run differently when called from browser vs. called from Java?

我在 Cosmos DB 模拟器中有一个存储过程。此过程所做的只是:删除 mycollection 中的所有文档。当我在浏览器 (https://localhost:8081/_explorer/index.html) 中运行它时,效果很好。然后我尝试从 Java 调用它:

1
2
3
4
5
RequestOptions requestOptions = new RequestOptions();
requestOptions.setPartitionKey(new PartitionKey(null));
System.out.println("START DELETE PROCEDURE");
StoredProcedureResponse spr = client.executeStoredProcedure(sprocLink, requestOptions, null);    
System.out.println(spr.getResponseAsString());

并得到如下结果:{"deleted": 0,"continuation": false}

这太疯狂了。我正在从浏览器运行这个存储过程并得到这个结果:{"deleted": 10,"continuation": false}。然后(当然添加回这 10 个文档)从 Java 运行这个结果并得到这个结果:{"deleted": 0,"continuation": false}

因此,当存储过程由 Java 运行时,它被调用但没有完成工作。什么都没删除……为什么会这样?

下面是存储过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
   function testStoredProcedure( ) {
       var collection = getContext().getCollection();
        var collectionLink = collection.getSelfLink();
        var response = getContext().getResponse();
        var responseBody = {
            deleted: 0,
            continuation: true
        };

        var query = 'SELECT * FROM mycollection   ';

    // 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();
        }
    }
}


对于分区容器,在执行存储过程时,必须在请求选项中提供分区键值。存储过程始终限定为分区键。具有不同分区键值的项目对存储过程不可见。这也适用于触发器。

您在 requestOptions 中将分区键设置为"null"。"null"是一个有效的分区键值。看起来"null"不是您的 10 个文档的分区键值。


谦虚转贴@Jay Gong 回答 如何指定NONE 分区键来删除Document DB java SDK 中的文档?

也许它会对某人有所帮助。放:

PartitionKey partitionKey = new PartitionKey(Undefined.Value());