2015-06-03 3 views
3

В каждом документе,Как я могу удалить дублированные элементы (комплекс объектов) из массива

в records представляет собой массив, содержащий много дублированных объектов.

и в buy_items есть также много дублированных предметов.

Как можно очистить дублированные предметы?

Оригинальные документы:

{ 
    "_id": "0005d116qwwewdq82a1b84f148fa6027d429f3e", 
    "records": [ 
    { 
     "DATE": new Date("1996-02-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 ", 
     "5210 ", 
     "5210 " 
     ] 
    }, 
    { 
     "DATE": new Date("1996-02-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 ", 
     "5210 ", 
     "5210 " 
     ] 
    } 
    { 
     "DATE": new Date("2012-12-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 ", 
     "1234 ", 
     " " 
     ] 
    }   
    ] 
} 

Ожидаемый результат:

{ 
    "_id": "0005d116qwwewdq82a1b84f148fa6027d429f3e", 
    "records": [ 
    { 
     "DATE": new Date("1996-02-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 " 
     ] 
    }, 
    { 
     "DATE": new Date("2012-12-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 ", 
     "1234 ", 
     " " 
     ] 
    }  
    ] 
} 

С решением Michaels, вывод может выглядит эта

{ 
    "_id": "0005d116qwwewdq82a1b84f148fa6027d429f3e", 
    "records": [ 
    "date": new Date("1996-02-08T08:00:00+0800"), 
     "buy_items": [ 
     "5210 " 
     "1234 ", 
     " " 
     ] 
    ] 
} 
+0

Вы можете сделать это с рамками агрегации: 1. разматывать записи 2. unwind buy_items 3. перегруппируйте buy_items с помощью addToSet 4.перегруппируйте записи с помощью addToSet , затем выполните итерацию по набору результатов и обновите документы – RomanKonz

+0

, вы хотите обновить свои коллекции или хотите отображать их с помощью агрегации? – Yogesh

+0

@yogesh обновить коллекцию – newBike

ответ

3

Вы можете удалить duplic Объекты ованные с использованием aggregation framework

db.collection.aggregate(
    [ 
     { $unwind: "$records" }, 
     { $unwind: "$records.buy_items" }, 
     { $group: { "_id": {id: "$_id", date: "$records.DATE" }, buy_items: { $addToSet: "$records.buy_items" }}}, 
     { $group: {"_id": "$_id.id", records: { $push: {"date": "$_id.date", "buy_items": "$buy_items" }}}}, { $sort: { "records.0.date": 1 }} , 
     { $out: "collection" } 
    ] 
) 

В $out оператора позволяют записать свой результат агрегации в указанной коллекции или Заменить Вы существующие коллекции.


Даже лучше, используя "Bulk" операции

var bulk = bulk = db.collection.initializeOrderedBulkOp(), 
    count = 0; 

db.collection.aggregate([ 
    { "$unwind": "$records" }, 
    { "$project": { 
     "date": "$records.DATE", 
     "buy_items": { "$setIntersection": "$records.buy_items" } 
    }}, 
    { "$unwind": "$buy_items" }, 
    { "$group": { 
     "_id": { "id": "$_id", "date": "$date" }, 
     "buy_items": { "$addToSet": "$buy_items" } 
    }}, 
    { "$group": { 
     "_id": "$_id.id", 
     "records": { "$push": { 
      "date": "$_id.date", 
      "buy_items": "$buy_items" 
     }} 
    }} 
]).forEach(function(doc) { 
     bulk.find({"_id": doc._id}).updateOne({ 
     "$set": { "records": doc.records } 
     }); 
     count++; 
     if (count % 500 == 0) { 
      bulk.execute();  
      bulk = db.collection.initializeOrderedBulkOp(); 
     } 
}) 

if (count % 500 != 0) 
    bulk.execute(); 

Результат:

{ 
    "_id" : "0005d116qwwewdq82a1b84f148fa6027d429f3e", 
    "records" : [ 
      { 
        "date" : ISODate("2012-12-08T00:00:00Z"), 
        "buy_items" : [ 
          " ", 
          "1234 ", 
          "5210 " 
        ] 
      }, 
      { 
        "date" : ISODate("1996-02-08T00:00:00Z"), 
        "buy_items" : [ 
          "5210 " 
        ] 
      } 
    ] 
} 
1

Если вы хотите обновить свои текущие коллекции без создания новой коллекции и падение предыдущей коллекции. Я пробовал это, но при этом вы должны запускать две разные команды обновления.

Первого обновления records с distinct, как это:

db.collectionName.update({},{"$set":{"records":db.collectionName.distinct('records')}}) 

и вторым обновление для buy_items с distinct, как это:

db.collectionName.update({},{"$set":{"records.0.buy_items":db.collectionName.distinct('records.buy_items')}}) 

Если вы хотите, чтобы избежать два запроса на обновление затем следует Майкл ответа ,

1

Вы могли бы попробовать использовать forEach() метод find() курсора перебрать свойства каждого документа, проверить уникальность и фильтровать различные значения следующим образом:

db.collection.find().forEach(function(doc){ 
    var records = [], seen = {}; 
    doc.records.forEach(function (item){ 
     var uniqueBuyItems = item["buy_items"].filter(function(i, pos) { 
      return item["buy_items"].indexOf(i) == pos; 
     }); 
     item["buy_items"] = uniqueBuyItems; 
     if (JSON.stringify(item["buy_items"]) !== JSON.stringify(seen["buy_items"])) { 
      records.push(item); 
      seen["buy_items"] = item["buy_items"]; 
     }   
    }); 
    doc.records = records; 
    db.collection.save(doc); 
}) 
Смежные вопросы