【问题标题】:How to delete many documents in a partitioned collection in Azure CosmosDB using MongoDB API如何使用 MongoDB API 删除 Azure CosmosDB 中分区集合中的许多文档
【发布时间】:2019-03-05 11:10:51
【问题描述】:

考虑以下文档类型

class Info
{
    public string Id { get; set; }
    public string UserId { get; set; }  // used as partition key
    public DateTime CreatedAt { get; set; }
}

我用这个创建了一个集合

var bson = new BsonDocument
{
    { "shardCollection", "mydb.userInfo" },
    { "key", new BsonDocument(shardKey, "hashed") }
};
database.RunCommand(new BsonDocumentCommand<BsonDocument>(bson));

要删除所有早于某个日期的文档,我试过这个

collection.DeleteManyAsync(t => t.CreatedAt >= date);

但是Command delete failed: query in command must target a single shard key. 失败了我的问题是,我应该如何跨多个分区有效地删除这些文档?在这种情况下,我不是在寻找如何选择分区键的答案。我认为总会有我必须跨所有分区运行修改查询的情况。

我可以先用collection.Find(t =&gt; t.CreatedAt &gt;= date) 查询文档,然后为每组分区键运行DeleteManyAsync(t =&gt; idsInThatPartition.Contains(t.Id) &amp;&amp; t.UserId == thatPartitionKey),但我真的希望有更好的方法。示例代码:

var affectedPartitions = await collection.Aggregate()
    .Match(i => i.CreatedAt >= date)
    .Group(i => i.UserId, group => new { Key = group.Key })
    .ToListAsync();

foreach (var partition in affectedPartitions)
{
    await collection.DeleteManyAsync(
        i => i.CreatedAt >= date && i.UserId == partition.Key);
}

【问题讨论】:

  • 这可能是另一个与实现相关的“Cosmos DB”特定事物。 MongoDB 不会针对“多”或“多”变体发出该投诉。仅当您使用 updateOne()deleteOne() 并且不包含分片键时,才会从 MongoDB 引发错误。这里最合理的回应是,因为这不是 MongoDB,所以不要期望它会像 MongoDB 一样做所有事情。
  • 仅供参考:Single Document Modification Operations in Sharded Collections。当然,github.com/MicrosoftDocs/azure-docs/issues/12292 但既然你已经在那里发帖了,你应该知道这一点。简而言之,MongoDB 本身按设计工作。
  • @NeilLunn 感谢您的评论。当然,这是一个 cosmosdb 问题。我已经知道 MongoDB 中的“多”事物,但在 cosmosdb 中找不到如何做到这一点。也许 MongoDB 标记具有误导性......这个问题更多的是关于解决对跨分区查询的缺失支持。
  • 我明白这一点,而且我的 cmets 可能更适合“其他读者”而不是您自己。我不会抱太大希望,主要是因为我自己和其他人已经“清理”了各种 CosmosDB 问题,这些问题归结为 MongoDB 实际所做的不受支持的事情。基本上这里有一个模板答案,它基本上说:“CosmosDB 不是 MongoDB,所以不要指望它会一样工作”。我不确定是否有本地 API 方式来进行查询,但很明显 MongoDB API 兼容性在这里没有正确完成。

标签: c# mongodb azure azure-cosmosdb mongodb-.net-driver


【解决方案1】:

我遇到了同样的问题,最后发现目前无法实现,Azure CosmosDb 团队正在研究解决方案,暂定于 2019 年第一个月发布

https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/34813063-cosmosdb-mongo-api-delete-many-with-partition-ke

拭目以待:(

【讨论】:

  • 不可能的事实是问题的一部分。这里的问题是如何有效地解决这个问题。我无法想象任何严肃的现实世界项目都可以始终在单个分区上工作。
  • 仅供参考,我现在发布的链接说:“已在 Cosmos DB API 中为 Mongo DB 服务器版本 3.6 修复。” ;)
【解决方案2】:

我不了解特定于 C# 的语法,但我设法通过 MongoDB 批量操作解决了这个问题。

这个解决方案远非完美,但这是我能想到的唯一解决方法。

这是我如何在 Nodejs 上实现的示例:

//First find all your document you want to Update/Delete
const res = await model.find(query).lean().exec()

//Initialize bulk operation object
var bulk = model.collection.initializeUnorderedBulkOp();

//Iterate the results
res.forEach((item: any) => {

    //Find your document with your shared key ( my shared key is the document _id)
    bulk.find({ _id: item._id }).removeOne();
})

//Check if should excute the bulk operation
if (bulk.length > 0)
    //Execute all operations at once
    return await bulk.execute();

参考MongoDB批量操作https://docs.mongodb.com/manual/reference/method/Bulk/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2018-10-09
    • 1970-01-01
    • 2020-07-17
    • 2020-09-16
    • 2018-11-09
    • 1970-01-01
    相关资源
    最近更新 更多