我想将我的原始文档更新为预期文档
即删除重复的连续相同的价格记录,
只保留最后一个
如何使用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
}
]
}
标题>
您可以使用聚合框架将数组减少到所需的项,然后使用结果更新集合中的每个文档。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
选项,如上面所示。