如何删除重复的嵌入文档

时间:2015-03-09 11:48:02

标签: mongodb indexing duplicates mongodb-query

我的用户集合包含许多子文档列表。架构是这样的:

   {
    _id: ObjectId(),
    name: aaa,
    age: 20,
    transactions:[
        {
         trans_id: 1,
         product: mobile,
         price: 30,
        },
        {
         trans_id: 2,
         product: tv,
         price: 10
        },
        ...]
    ...
   }

所以我有一个疑问。 trans_id列表中的transactions对于所有产品都是唯一的,但我可能会使用相同的trans_id再次复制相同的事务(由于错误的ETL编程)。现在我想删除那些重复的子文档。我已经将trans_id编入索引而不是unique。我读到了dropDups选项。但是它会删除DB中存在的特定副本,还是会丢弃整个文档(我绝对不想要)。如果没有怎么办?

PS:我使用的是MongoDB 2.6.6版本。

1 个答案:

答案 0 :(得分:2)

我们在这里看到的所有人都知道最近的情况,现在你需要一种方法来定义数组中的“不同”项目,其中某些项目实际上是数组中其他项目的“精确副本”。

最好的情况是在集合的循环操作中使用$addToSet$each修饰符。理想情况下,您可以使用Bulk Operations API来减少流量,这样做:

var bulk = db.collection.initializeOrderedBulkOperation();
var count = 0;

// Read the docs
db.collection.find({}).forEach(function(doc) {
    // Blank the array
    bulk.find({ "_id": doc.id })
        .updateOne({ "$set": { "transactions": [] } });
    // Resend as a "set"
    bulk.find({ "_id": doc.id })
        .updateOne({ 
            "$addToSet": { 
                "trasactions": { "$each": doc.transactions }
            }
        });
    count++;

    // Execute once every 500 statements ( actually 1000 )
    if ( count % 500 == 0 ) {
        bulk.execute()
        bulk = db.collection.initializeOrderedBulkOperation();
    }
});

// If a remainder then execute the remaining stack
if ( count % 500 != 0 )
    bulk.execute();

因此,只要“重复”内容“完全相同”,那么这种方法就可以了。如果唯一实际上是“重复”的是“trans_id”字段,那么你需要一种完全不同的方法,因为“整个文档”都没有“重复”,这意味着你需要更多的逻辑来实现这一点。 / p>