Как удалить дубликаты записей из массива? - PullRequest
18 голосов
/ 25 марта 2012

Как удалить дубликаты записей из массива?

В приведенном ниже примере «Алгоритмы в C ++» добавляются дважды.

$ unset модификатор удаляет конкретное поле, но как удалить запись из поля?

> db.users.find()

{ "_id" : ObjectId("4f6cd3c47156522f4f45b26f"), 
 "favorites" : { "books" : [ "Algorithms in C++",    
                            "The Art of Computer Programmning", 
                            "Graph Theory",      
                            "Algorithms in C++" ] }, 
  "name" : "robert" }

Ответы [ 3 ]

32 голосов
/ 04 июня 2013

Начиная с MongoDB 2.2, вы можете использовать структуру агрегирования с этапами $unwind, $group и $project для достижения этого:

db.users.aggregate([{$unwind: '$favorites.books'},
                    {$group: {_id: '$_id',
                              books: {$addToSet: '$favorites.books'},
                              name: {$first: '$name'}}},
                    {$project: {'favorites.books': '$books', name: '$name'}}
                   ])

Обратите внимание на необходимость$project для переименования поля favorites, поскольку совокупные поля $group не могут быть вложенными.

5 голосов
/ 24 сентября 2018

Самое простое решение - использовать setUnion (Mongo 2.6 +):

db.users.aggregate([
    {'$addFields': {'favorites.books': {'$setUnion': ['$favorites.books', []]}}}
])

Другая (более длинная) версия, основанная на идее ответа @ kynan's , но сохраняет все остальные поля без явного их указания (Mongo 3.4 +):

> db.users.aggregate([
    {'$unwind': {
        'path': '$favorites.books',
        // output the document even if its list of books is empty
        'preserveNullAndEmptyArrays': true
    }},
    {'$group': {
        '_id': '$_id',
        'books': {'$addToSet': '$favorites.books'},
        // arbitrary name that doesn't exist on any document
        '_other_fields': {'$first': '$$ROOT'},
    }},
    {
      // the field, in the resulting document, has the value from the last document merged for the field. (c) docs
      // so the new deduped array value will be used
      '$replaceRoot': {'newRoot': {'$mergeObjects': ['$_other_fields', "$$ROOT"]}}
    },
    // this stage wouldn't be necessary if the field wasn't nested
    {'$addFields': {'favorites.books': '$books'}},
    {'$project': {'_other_fields': 0, 'books': 0}}
])

{ "_id" : ObjectId("4f6cd3c47156522f4f45b26f"), "name" : "robert", "favorites" : 
{ "books" : [ "The Art of Computer Programmning", "Graph Theory", "Algorithms in C++" ] } }    
4 голосов
/ 26 марта 2012

То, что вам нужно сделать, это использовать карту, чтобы уменьшить и обнаружить дубликаты тегов .. затем использовать $set, чтобы заменить целые книги на основе { "_id" : ObjectId("4f6cd3c47156522f4f45b26f"),

Это обсуждалось несколько раз здесь ..см.

Удаление дубликатов записей с помощью MapReduce

Быстрый способ поиска дубликатов в проиндексированном столбце в mongodb

http://csanz.posterous.com/look-for-duplicates-using-mongodb-mapreduce

http://www.mongodb.org/display/DOCS/MapReduce

Как удалить дубликат записи в MongoDB с помощью MapReduce?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...