这是我的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"
}
]
}
答案 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"
}
]
}