You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Cosmos DB删除文档时出现Resource not found错误的排查求助

Azure Cosmos DB按日期范围删除文档返回404 NotFound错误

问题描述

我编写了C#代码,试图删除Azure Cosmos DB中指定日期范围内的文档。查询能正常返回目标文档,且在Azure Data Explorer中也能找到对应ID和分区键的文档,但执行删除时全部失败,抛出404错误。

代码实现

public async Task<int> DeleteDocumentsByDateRangeSimple(DateTime fromDate, DateTime toDate)
{
        int deletedCount = 0;
        try
        {
            using CosmosClient client = new CosmosClient($"AccountEndpoint={endpoint};AccountKey={accountKey}");
            Microsoft.Azure.Cosmos.Database db = client.GetDatabase("telemetrydata");
            Container container = db.GetContainer("iothub");

            string sfromDate = fromDate.ToString("yyyy-MM-dd\THH:mm:ss");
            string stoDate = toDate.ToString("yyyy-MM-dd\THH:mm:ss");

            var query = new QueryDefinition(
                "SELECT c.id, c.partitionKey FROM c WHERE c.Body.TimeStamp >= @minDate AND c.Body.TimeStamp <= @maxDate"
            )
            .WithParameter("@minDate", sfromDate)
            .WithParameter("@maxDate", stoDate);

            using FeedIterator<dynamic> feed = container.GetItemQueryIterator<dynamic>(query);
            while (feed.HasMoreResults)
            {
                var response = await feed.ReadNextAsync();
                foreach (var doc in response)
                {
                    try
                    {
                        string id = doc.id?.ToString()?.Trim('"');
                        string partitionKey = doc.partitionKey?.ToString()?.Trim('"');
                        if (string.IsNullOrEmpty(id))
                        {
                            Debug.WriteLine($"Skipping document with missing id");
                            continue;
                        }

                        var deleteResponse = await container.DeleteItemAsync<dynamic>(id, new PartitionKey(partitionKey));
                        if (deleteResponse.StatusCode == System.Net.HttpStatusCode.NoContent)
                        {
                            deletedCount++;
                        }
                        else
                        {
                            Debug.WriteLine($"Delete returned status {deleteResponse.StatusCode} for id={id}, pk={partitionKey}");
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"Failed to delete document id={doc.id}, partitionKey={doc.partitionKey}: {ex.Message}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"DeleteDocumentsByDateRangeSimple() : Unexpected error : {ex.Message}");
        }
        return deletedCount;
}

错误日志

Failed to delete document id=6aa773ff-54cb-4837-9620-653d58a2bf5f, partitionKey=VK_THC_GreenRoom: Response status code does not indicate success: NotFound (404); Substatus: 0; ActivityId: a6858546-110a-45e6-8fec-e56ef7571b44; Reason: (
Errors : [
  "Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found"
]
);

可能的原因及解决办法

  • 分区键字段匹配错误
    这是最常见的原因:你查询中获取的c.partitionKey可能并不是容器实际配置的分区键字段。比如你的容器分区键可能是/Body/DeviceId或其他字段,而非名为partitionKey的字段。删除操作必须使用正确的分区键值才能定位到文档,用错字段自然会返回404。
    解决:登录Azure门户,查看目标容器的分区键配置,修改查询语句,选择正确的分区键字段(比如如果分区键是/DeviceId,查询就写SELECT c.id, c.DeviceId FROM c ...),删除时用该字段的值作为PartitionKey参数。

  • 动态类型解析导致的键值失真
    使用dynamic类型接收查询结果时,容易出现类型解析问题。比如doc.id或doc.partitionKey的ToString()可能返回带引号的字符串(如果底层是JSON对象的字符串值),或者解析后的类型与实际文档的键类型不匹配(比如分区键是数字,你却转成了字符串)。
    解决:定义强类型类来接收查询结果,避免动态类型的不确定性:

    public class DocIdentifier
    {
        public string id { get; set; }
        // 这里的字段名要和容器实际分区键字段一致
        public string DeviceId { get; set; } 
    }
    

    然后将查询迭代器改为FeedIterator<DocIdentifier>,直接获取正确的键值,无需额外的Trim('"')操作。

  • 分区键类型不匹配
    如果文档的分区键是非字符串类型(比如数字、布尔值),你将其转为字符串后传入PartitionKey,会导致定位失败。Cosmos DB对分区键的类型严格匹配,字符串类型的"123"和数字类型的123会被视为不同的分区键。
    解决:检查文档分区键的实际类型,创建PartitionKey时使用对应类型的值,比如分区键是数字就传入new PartitionKey(123),而非字符串。

  • 容器或数据库引用错误
    虽然概率较低,但要确认代码中指定的数据库名telemetrydata和容器名iothub与你在Data Explorer中查看的完全一致,避免误操作了其他环境的资源。


内容的提问来源于stack exchange,提问作者László Frank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 17:44:52