如何更新数组中特定的重复项?



我想将我的原始文档更新为预期文档

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

只保留最后一个

如何使用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 选项,如上面所示。

相关内容

  • 没有找到相关文章

最新更新