Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB更新最新子文档_Mongodb_Mongodb Query - Fatal编程技术网

MongoDB更新最新子文档

MongoDB更新最新子文档,mongodb,mongodb-query,Mongodb,Mongodb Query,这是我的mongo文件 { "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8"), "subscriptions" : [ { "sub_id" : "5a56fd399dd78e33948c9b8e", "invoice_id" : "5a56fd399dd78e33948c9b8d" }, { "sub_id" : "

这是我的mongo文件

{
    "_id" : ObjectId("5a69d0acb76d1c2e08e4ccd8"),
    "subscriptions" : [ 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e",
            "invoice_id" : "5a56fd399dd78e33948c9b8d"
        }, 
        {
            "sub_id" : "5a56fd399dd78e33948c9b8e"
        }
    ]
}
我想更新发票id并将其插入子数组的最后一个元素。。 我已经试过了。
排序:{$natural:-1},
订购。$发票

我想要的是

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

我们可以通过索引获取文档并更新最后一个元素

> 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"
        }
    ]
}

虽然有办法获得最后一个数组元素,就像Saravana在她的回答中所显示的那样,但我不建议这样做,因为它引入了竞争条件。例如,如果同时添加两个sub,则无法确定数组中哪一个是“最后一个”

如果发票id必须绑定到特定的子id,那么最好在数组中查询并找到该特定元素,然后将发票id添加到其中

在注释中,OP指出当前操作顺序是1)添加子发票id,2)将发票记录插入发票集合并获取发票id,3)将发票id添加到新订阅中

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


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

请问您为什么选择该数据结构?有时,当一个数据结构对于您想要做的事情被证明是笨拙的时候,重新考虑数据结构是值得的。从语义上讲,数组中的每个元素/对象都应该具有相同的数据结构。这并不意味着每个对象都应该具有所有可能的属性,而是应该允许所有属性。在您的情况下,这意味着每个数组元素都应该有一个invoice\u id。如果不是这样,那么应该将invoice\u id移出数组。在我的情况下,我正在执行。。1.将订阅id添加到订阅中,然后添加到订阅2中。将发票详细信息添加到发票集合中…然后3.将新添加的发票记录的\u id添加到新添加的订阅中,即在步骤1中。每个订阅是否可以有发票?还是只有最新的订阅?另外,在您的示例中,我注意到sub_id对于所有元素都是相同的。这是真的吗,或者只是为了本例的目的而进行的快速剪切/粘贴?如果子_id确实都是相同的,那么您应该将其从数组中拉出,并将其存储为父对象的属性,然后该数组只是一个发票数组。OTOH,如果子_id不同,我强烈建议您通过首先找到具有正确sub_id的数组元素来添加invoice_id。简单地将其添加到最后一个元素可以引入竞争条件(例如,如果同时添加两个sub,您不能依赖于数组中哪一个是“最后的”),如果您已经拥有subscription_id,为什么不先将发票详细信息添加到发票集合中,这样就可以获得发票id,然后可以将一个对象同时推送到具有子发票id和发票id的数组中。这将提供更好的性能(只更新订阅数组一次),更重要的是,消除竞争条件(因为整个对象是在一个操作中添加的)。