Найдите повторяющиеся записи в MongoDB

118

Как найти повторяющиеся поля в коллекции mongo.

Я хочу проверить, не дублируются ли какие-либо поля "name".

{
    "name" : "ksqn291",
    "__v" : 0,
    "_id" : ObjectId("540f346c3e7fc1054ffa7086"),
    "channel" : "Sales"
}

Большое спасибо!

Крис
источник
5
Повторяющийся флаг для этого вопроса незаслужен. Этот вопрос спрашивает, как найти повторяющиеся записи, а не предотвратить их.
Гарри Кинг

Ответы:

213

Используйте агрегацию на nameи получить nameс count > 1:

db.collection.aggregate([
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
]);

Чтобы отсортировать результаты по наименьшему количеству дубликатов:

db.collection.aggregate([
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$sort": {"count" : -1} },
    {"$project": {"name" : "$_id", "_id" : 0} }     
]);

Чтобы использовать с другим именем столбца, кроме "name", замените " $ name " на " $ column_name "

anhlc
источник
1
"$match": {"_id" :{ "$ne" : null } - здесь не требуется, так как второй части оператора было бы достаточно для фильтрации результата. Так что достаточно проверить наличие группы count > 1.
BatScream
5
Ткс @BatScream. {"$ ne": null} на тот случай, если 'name' равно нулю или не существует. Агрегация также будет считаться нулевой.
anhlc
1
Добро пожаловать. Но тогда зачем проверять _idполе. После groupоперации всегда гарантируется, что он не будет нулевым .
BatScream
4
_idДокумента от $groupстадии может быть пустым.
wdberkeley
1
Что это будет на выходе? Если я запустил, я получу все документы, которые мне нужны, это только дублированные идентификаторы / имена.
Kannan T
24

Вы можете найти listиз duplicateимен с помощью следующего aggregateтрубопровода:

  • Groupвсе записи похожие name.
  • Matchте groups, у кого записи больше 1.
  • Затем groupснова ко projectвсем повторяющимся именам в виде файла array.

Код:

db.collection.aggregate([
{$group:{"_id":"$name","name":{$first:"$name"},"count":{$sum:1}}},
{$match:{"count":{$gt:1}}},
{$project:{"name":1,"_id":0}},
{$group:{"_id":null,"duplicateNames":{$push:"$name"}}},
{$project:{"_id":0,"duplicateNames":1}}
])

о / п:

{ "duplicateNames" : [ "ksqn291", "ksqn29123213Test" ] }
BatScream
источник
10

Ответ, данный anhic, может быть очень неэффективным, если у вас большая база данных, а имя атрибута присутствует только в некоторых документах.

Для повышения эффективности вы можете добавить в агрегирование $ match.

db.collection.aggregate(
    {"$match": {"name" :{ "$ne" : null } } }, 
    {"$group" : {"_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)
Хуанин
источник
3
db.getCollection('orders').aggregate([  
    {$group: { 
            _id: {name: "$name"},
            uniqueIds: {$addToSet: "$_id"},
            count: {$sum: 1}
        } 
    },
    {$match: { 
        count: {"$gt": 1}
        }
    }
])

Первая группа. Запросите группу в соответствии с полями.

Затем мы проверяем уникальный идентификатор и подсчитываем его. Если count больше 1, то поле дублируется во всей коллекции, так что это должно обрабатываться запросом $ match.

Аман Шривастава
источник
1
не смог заставить это работать и для меня. Голосование против!
Mathieu G
Этот пост старый, но может кому-то помочь. проверьте это, я проверю в своем местном, он работает. Даже я наткнулся на один блог по этому поводу. Пожалуйста, посмотрите. compose.com/articles/finding-duplicate-documents-in-mongodb
Аман шривастава
Мне удалось заставить его работать - отредактировал для обновления до подтвержденной рабочей версии.
AL Strine,