MongoDB更新最新的子文档

时间:2018-01-26 06:54:32

标签: mongodb mongodb-query

这是我的mongo文件..

{
    "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8"),
    "subscriptions" : [ 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e",
            "invoice_id" : "5a56fd399dd78e33948c9b8d"
        }, 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e"
        }
    ]
}

我想更新并将invoice_id更新为子数组的最后一个元素.. 我试过..
                  sort:{$ natural:-1},
     订阅。$。发票

我想要的是......

{
    "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8"),
    "subscriptions" : [ 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e",
            "invoice_id" : "5a56fd399dd78e33948c9b8d"
        }, 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e",
            "invoice_id" : "5a56fd399dd78e33948c9b8f"
        }
    ]
}

2 个答案:

答案 0 :(得分:2)

虽然有很多方法可以获得最后一个数组元素,比如Saravana在她的回答中显示,但我不建议这样做,因为它引入了竞争条件。例如,如果同时添加两个subs,则不能依赖于哪个是数组中的“last”。

如果必须将invoice_id绑定到特定的sub_id,那么查询并查找数组中的特定元素会更好,然后将invoice_id添加到其中。

在评论中,OP表示当前的操作顺序是1)添加sub_id,2)将发票记录插入INVOICE集合并获取invoice_id,3)将invoice_id添加到新订阅中。

但是,如果您已经拥有sub_id,那么最好以这种方式重新排序您的操作:1)插入发票记录并获取invoice_id 2)添加两者 sub_id和invoice_id单一操作。

这样做可以提高性能(消除第二次更新操作),但更重要的是,消除竞争条件,因为您同时添加了sub_id和invoice_id。

答案 1 :(得分:1)

我们可以获取文档并按索引

更新最后一个元素
> var doc = db.sub.findOne({"_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8")})

> if ( doc.subscriptions.length - 1 >= 0 ) 
    doc.subscriptions[doc.subscriptions.length-1].invoice_id="5a56fd399dd78e33948c9b8f"

> db.sub.update({_id:doc._id},doc)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

或编写汇总管道以形成文档并将其用于更新

db.sub.aggregate(
    [
        {$match : { "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8") }},
        {$addFields : { last : { $subtract : [{$size : "$subscriptions"},1]}}},
        {$unwind : { path :"$subscriptions" , includeArrayIndex : "idx"}},
        {$project : { "subscriptions.sub_id" : 1, 
                    "subscriptions.invoice_id" : {
                        $cond : {
                            if: { $eq: [ "$idx", "$last" ] },
                            then: "5a56fd399dd78e33948c9b8f",
                            else: "$$REMOVE"
                        }
                    }
                }
        },
        {$group : {_id : "$_id", subscriptions : {$push : "$subscriptions"}}}
    ]
).pretty()

结果文档

{
    "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8"),
    "subscriptions" : [
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e"
        },
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e",
            "invoice_id" : "5a56fd399dd78e33948c9b8f"
        }
    ]
}