Удалить все, кроме одного дубликата из пн go дБ - PullRequest
0 голосов
/ 13 апреля 2020

Так что я сошла с ума от ошибки и дважды сохранила множество документов, потому что испортила идентификатор своего документа. Поскольку я сделал Вставку, я умножал свои документы каждый раз, когда я их сохранял. Поэтому я хочу удалить все дубликаты, кроме первого, который я написал. К счастью, у документов есть неявный уникальный ключ (match._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'}]

Теперь я не знаю, как действовать дальше, так как в агрегациях нет операции «удалить», и я Я не хочу записывать эти временные данные в БД только для того, чтобы я мог написать команду удаления с этим, поскольку я хочу удалить их в одном go. Есть ли другой способ сделать это? Я все еще учусь на mongodb и чувствую себя немного ошеломленным: /

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Я думаю, что вы на правильном пути, однако, чтобы удалить найденные дубликаты, вы можете использовать массовую запись в коллекции.

Так что, если мы представим вас запрос агрегации сохранил следующее в коллекции 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)

, тогда все дубликаты будут удалены.

1 голос
/ 14 апреля 2020

Вместо того, чтобы делать все это, вы можете просто выбрать первый документ в group для каждого _id: "$match._id" и сделать его root документом. Кроме того, я не думаю, что вам нужно выполнять сортировку в вашем случае:

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

Тест: MongoDB-Playground

...