【问题标题】:Cosmos DB - Deleting a documentCosmos DB - 删除文档
【发布时间】:2017-10-22 08:15:06
【问题描述】:

如何从 Cosmos DB 中删除单个记录?

我可以使用 SQL 语法进行选择:

SELECT *
FROM collection1
WHERE (collection1._ts > 0)

确实返回了所有文档(类似于行?)

但是当我尝试删除时这不起作用

DELETE
FROM collection1
WHERE (collection1._ts > 0)

我如何做到这一点?

【问题讨论】:

    标签: azure azure-cosmosdb


    【解决方案1】:

    DocumentDB API 的 SQL 专门用于查询。也就是说,它只提供SELECT,而不提供UPDATEDELETE

    完全支持这些操作,但需要调用 REST(或 SDK)。例如,对于 .net,您将调用 DeleteDocumentAsync()ReplaceDocumentAsync(),而在 node.js 中,这将是对 deleteDocument()replaceDocument() 的调用。

    在您的特定场景中,您可以运行 SELECT 来识别要删除的文档,然后进行“删除”调用,每个文档一个(或者,为了提高效率和事务性,将要删除的文档数组传递到存储的程序)。

    【讨论】:

    • 啊,好的,另一块拼图已经到位。我正在使用 Python,可以看到 DeleteDocument()。谢谢!
    • java版本的SDK可以吗?
    • @blackuprise - 是的,Java 完全支持这一点。你会发现DocumentClientdeleteDocument() 方法。
    • @DavidMakogon 可以在没有分区键的情况下使用 deleteDocument 吗?我正在使用存储过程,但它不起作用。
    【解决方案2】:

    最简单的方法可能是使用Azure Storage Explorer。连接后,您可以深入选择一个容器,选择一个文档,然后将其删除。您可以在 https://gotcosmos.com/tools 上找到适用于 Cosmos DB 的其他工具。

    【讨论】:

    • 有没有办法在 Azure 存储资源管理器中一次删除多个文档?
    【解决方案3】:

    另一个需要考虑的选项是生存时间 (TTL)。您可以为集合打开此功能,然后为文档设置过期时间。文件过期后会自动为您清理。

    【讨论】:

    • 迄今为止我发现的最简单的解决方案
    • 对我不起作用。将 TTL 设置为 1 秒后。文件不可见,但回到 TTL 关闭后,文件又出现了。
    • @DOminikMinc 也许你需要再等一会儿。云需要一些时间才能删除项目。
    【解决方案4】:

    使用以下代码创建一个存储过程:

    /**
     * A Cosmos DB stored procedure that bulk deletes documents for a given query.
     * Note: You may need to execute this stored procedure multiple times (depending whether the stored procedure is able to delete every document within the execution timeout limit).
     *
     * @function
     * @param {string} query - A query that provides the documents to be deleted (e.g. "SELECT c._self FROM c WHERE c.founded_year = 2008"). Note: For best performance, reduce the # of properties returned per document in the query to only what's required (e.g. prefer SELECT c._self over SELECT * )
     * @returns {Object.<number, boolean>} Returns an object with the two properties:
     *   deleted - contains a count of documents deleted
     *   continuation - a boolean whether you should execute the stored procedure again (true if there are more documents to delete; false otherwise).
     */
    function bulkDeleteStoredProcedure(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();
            }
        }
    }
    

    并使用您的分区键(例如:null)和查询以选择文档(例如:SELECT c._self FROM c 删除所有)来执行它。

    基于Delete Documents from CosmosDB based on condition through Query Explorer

    【讨论】:

    • @marc_s 我需要对查询使用相同的格式(例如 SELECT c._self FROM c)还是可以(SELECT * FROM c)。另外,分区键是分区键的名字吗?
    • 现在尝试了几个小时。如果我从 Azure 门户调用它,效果很好,并且当我从客户端 C# 应用程序调用它时不会失败。但从不删除任何记录。我究竟做错了什么?为什么我不能从我的客户端应用程序中删除记录?任何示例,包括。 c#客户端代码?
    • 无法使用此删除任何记录。返回 0 个已删除的文档。
    • 这不适用于 Azure 门户或 Cosmos 模拟器。它返回 0 条记录。
    【解决方案5】:

    这是一个如何使用 .net Cosmos SDK V3 使用 bulkDeleteStoredProcedure 的示例。

    由于执行边界,必须使用ContinuationFlag。

    private async Task<int> ExecuteSpBulkDelete(string query, string partitionKey)
        {
            var continuationFlag = true;
            var totalDeleted = 0;
            while (continuationFlag)
            {
                StoredProcedureExecuteResponse<BulkDeleteResponse> result = await _container.Scripts.ExecuteStoredProcedureAsync<BulkDeleteResponse>(
                    "spBulkDelete", // your sproc name
                    new PartitionKey(partitionKey), // pk value
                    new[] { sql });
    
                var response = result.Resource;
                continuationFlag = response.Continuation;
                var deleted = response.Deleted;
                totalDeleted += deleted;
                Console.WriteLine($"Deleted {deleted} documents ({totalDeleted} total, more: {continuationFlag}, used {result.RequestCharge}RUs)");
            }
    
            return totalDeleted;
        }
    

    和响应模型:

    public class BulkDeleteResponse
    {
        [JsonProperty("deleted")]
        public int Deleted { get; set; }
    
        [JsonProperty("continuation")]
        public bool Continuation { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-20
      • 2022-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多