2015-06-07 26 views
0

具体重复项目我想更新我原来的文档转换为预期文档我怎么能更新阵列

即删除重复的连续相同的价格纪录,

只保留最后一个。

如何用mongo查询做到这一点?

预期文档

{ 
    "_id": "2015-06-12-TPE-KIX", 
    "flight_date": new Date("2015-06-12T08:00:00+0800"), 
    "history": [ 
    { 
     "updated_at": new Date(1433515526965), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433607771762), 
     "price": 5490 
    } 
    ] 
} 

原始文档

{ 
    "_id": "2015-06-12-TPE-KIX", 
    "flight_date": new Date("2015-06-12T08:00:00+0800"), 
    "history": [ 
    { 
     "updated_at": new Date(1433492046834), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492048208), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492428642), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492430039), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433515526965), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433562561356), 
     "price": 5490 
    }, 
    { 
     "updated_at": new Date(1433603772299), 
     "price": 5490 
    }, 
    { 
     "updated_at": new Date(1433607771762), 
     "price": 5490 
    } 
    ] 
} 

回答

1

那么你可以使用聚合框架为手段,以阵列降低到所需的项目,然后更新每个文档集合中与结果。壳牌例子而已,但相同的基本逻辑也适用:

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

db.collection.aggregate([ 
    // Unwind the array 
    { "$unwind": "$history" }, 

    // Group by price on each document 
    { "$group": { 
     "_id": { 
      "_id": "$_id", 
      "flight_date": "$flight_date", 
      "price": "$history.price" 
     }, 
     "updated_at": { "$max": "$history.updated_at" } 
    }}, 

    // Sort by updated_at in each document 
    { "$sort": { "_id._id": 1, "updated_at": 1 } }, 

    // Group back per document 
    { "$group": { 
     "_id": "$_id._id", 
     "flight_date": { "$first": "$_id.flight_date" }, 
     "history": { 
      "$push": { 
       "updated_at": "$updated_at", 
       "price": "$_id.price" 
      } 
     } 
    }} 
]).forEach(function(doc) { 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "history": doc.history } 
    }); 
    count++; 

    // Send to server every 1000 and re-init 
    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp(); 
    } 
}); 

// Process any queued 
if (count % 1000 != 0) 
    bulk.execute(); 

所以,在结果数组减少到你想要像这样的内容:

{ 
    "_id" : "2015-06-12-TPE-KIX", 
    "flight_date" : ISODate("2015-06-12T00:00:00Z"), 
    "history" : [ 
      { 
        "updated_at" : ISODate("2015-06-05T14:45:26.965Z"), 
        "price" : 6740 
      }, 
      { 
        "updated_at" : ISODate("2015-06-06T16:22:51.762Z"), 
        "price" : 5490 
      } 
    ] 
} 

但如果你实际更新的文件,我将会减少数组的缩减量,而不是每个由光标读取的文档的代码,然后为每个文档发送类似的批量更新请求。

$unwind操作对文档集合有很大的开销,而且由于实际上并没有在文档间“聚集”,所以在客户端代码中操作数组的方法是最有效的。

当然,如果您可以住在新的集合中,或者很乐意重命名集合,那么在集合中使用$out选项,如上所示。