如果某个项目无法读取,是否可以从 Cosmos 中删除该项目?

Can an item be removed from Cosmos if the item cannot be read?

我已经成功地使用 EF Core 在 Cosmos 中创建了以下项目:

    {
        "Code": "https://CokeURL.com/gbm330",
        "Quantity": 1,
        "StockItemId": "00000ff8-0000-0000-0000-000000000000",
        "id": "https://CokeURL.com/gbm330",
        "_rid": "-BdUAM1W389NAgAAAAAAAA==",
        "_self": "dbs/-BdUAA==/colls/-BdUAM1W388=/docs/-BdUAM1W389NAgAAAAAAAA==/",
        "_etag": "\"1e001ff0-0000-1100-0000-608004300000\"",
        "_attachments": "attachments/",
        "_ts": 1619002416
    }

我需要删除它,但我似乎需要先阅读该项目。我已经尝试通过 Cosmos 数据资源管理器,但单击该行会出现以下错误:

Failed to read item https://CokeURL.com/gbm330: Illegal characters ['/', '', '?', '#'] cannot be used in resourceId

我也试过使用 EF Core 删除,但这会引发一个异常,看起来它与 SQL API:

Response status code does not indicate success: NotFound (404); Substatus: 0; ActivityId: 7e652a49-9813-4959-b55e-57b228231d6a; Reason: (The value 'dbs/Stock/colls/StockItemCode/docs/https://CokeURL.com/gbm330' specified for query '$resolveFor' is invalid. ActivityId: 7e652a49-9813-4959-b55e-57b228231d6a, Linux/10 cosmos-netstandard-sdk/3.11.4);

还有其他删除项目的方法吗?

谢谢

有趣的问题!使用 SDK 将无法删除文档。

但是有一个解决方法。本质上,Cosmos DB 具有在 container/document 上设置 Time-to-Live (TTL) 属性 的功能。在文档级别正确设置后,一旦 TTL 到期,文档将自动删除。

然而,在此之前,您需要将容器上的 TTL 属性 设置为“开启”(默认为关闭)。此设置的意思是,如果在文档上指定了 TTL 并且一旦 TTL 过期,容器中的文档将自动删除。您可以通过 Azure 门户中的数据资源管理器进行设置,如下所示。

在容器级别正确配置 TTL 后,接下来需要做的是更新文档并在文档上设置 TTL 属性。您可以使用 Cosmos DB SDK 来执行此操作。请查看我将 TTL 设置为 30 秒的示例代码(您可以将其设置为低至 1 秒)。 upsert 操作成功后,您会看到文档在 TTL 过期后自动删除(在我的例子中是 30 秒)。

    static async Task UpdateItemTtl()
    {
        CosmosClient cosmosClient = new CosmosClient(connectionString);
        Container container = cosmosClient.GetContainer(databaseName, containerName);
        string documentBody = "{\"ttl\": 30, \"Code\": \"https://CokeURL.com/gbm330\", \"Quantity\": 1, \"ActivityId\": \"0000\", \"id\": \"https://CokeURL.com/gbm330\"}";
        Object o = JsonConvert.DeserializeObject(documentBody);
        ItemResponse<object> response = await container.UpsertItemAsync(o, new PartitionKey("0000"));
        documentBody = JsonConvert.SerializeObject(response.Resource);
        Console.WriteLine(documentBody);
    }