从 mongo 数据库中删除除一个副本之外的所有副本

Delete all but one duplicate from a mongo db

所以我犯了一个错误,两次保存了很多文档,因为我弄乱了我的文档 ID。因为我做了一个插入,所以我每次保存文件时都会成倍增加。所以我想删除我写的第一个以外的所有重复项。幸运的是,这些文件有一个隐含的唯一键(match._id),我应该能够分辨出第一个是什么,因为我使用的是对象 ID。

文件看起来像这样:

{
  _id: "5e8e2d28ca6e660006f263e6"
  match : {
    _id:  2345
    ...
  }
  ...
}

所以,现在我有一个聚合,告诉我哪些元素是重复的并将它们存储在一个集合中。肯定有更优雅的方法,但我还在学习。

[{$sort: {"$_id": 1},
{$group: {
  _id: "$match._id",
  duplicateIds: {$push: "$_id"},
  count: {$sum: 1}
}},
{$match: {
  count: { $gt: 1 }
}}, {$addFields: {
  deletableIds: { $slice: ["$duplicateIds", 1, 1000 ] }
}},
{$out: 'DeleteableIds'}]

现在我不知道如何进一步进行,因为它似乎没有聚合中的 "delete" 操作,我不想将这些临时数据写入数据库,这样我就可以写一个删除命令,因为我想一次性删除它们。还有其他方法吗?我仍在学习 mongodb,感觉有点不知所措:/

无需执行所有这些操作,您只需为每个 _id: "$match._id" 选择 group 中的第一个文档并将其作为根文档。另外,我认为您不需要对您的情况进行排序:

db.collection.aggregate([
  {
    $group: {
      _id: "$match._id",
      doc: {
        $first: "$$ROOT"
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: "$doc"
    }
  }, {$out: 'DeleteableIds'}
])

测试: MongoDB-Playground

我认为您的方向是正确的,但是,要删除您发现的重复项,您可以对集合使用 bulk write

因此,如果我们假设您的聚合查询将以下内容保存在 DeleteableIds 集合

> db.DeleteableIds.insertMany([
... {deletableIds: [1,2,3,4]},
... {deletableIds: [103,35,12]},
... {deletableIds: [345,311,232,500]}
... ]);

我们现在可以使用它们并编写批量写入命令:

const bulkwrite = db.DeleteableIds.find().map(x => ({ deleteMany : { filter: { _id: { $in: x.deletableIds } } } }))

然后我们可以对数据库执行。

> db.collection1.bulkWrite(bulkwrite)

这将删除所有重复项。