我想将原始文档更新为预期文档
即删除重复的连续相同价格记录,
只保留最后一个。
如何使用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
}
]
}
答案 0 :(得分:1)
您可以使用聚合框架作为将数组减少到所需项目的方法,然后使用结果更新集合中的每个文档。仅限Shell示例,但适用相同的基本逻辑:
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
选项和聚合,如上所示。