更新混合类型的猫鼬嵌套数组

Posted

技术标签:

【中文标题】更新混合类型的猫鼬嵌套数组【英文标题】:Updating mongoose nested array of mixed types 【发布时间】:2020-10-06 11:35:51 【问题描述】:

我有一个混合类型的猫鼬模式,如下所示:

const user = mongoose.Schema(
    ...
    "links" : []
    ...

填充此架构后,我最终得到如下数据:

[
    [
        
            "step1": "post-url-google", // This field is unique for each entry
            "step2": 
                "title": "Heading 1",
                "likes": 4
            
        ,
    ],

    [
        
            "step1": "post-url-microsoft",
            "step2": 
                "title": "Heading 1",
                "likes": 1
            
        ,

        
            "step1": "post-url-apple",
            "step2": 
                "title": "Heading 2",
                "likes": 6 // I want to update this to 7
            
        
    ]
]

我想要实现的是将 "step1": "post-url-apple" 字段从 6 更新为具有 7 的 likes 所以我尝试像这样使用User.save() 函数:

let user = await User.findOne("_id" : "some_id")

user.links[1].some(object => 
    if (object.step1 === "post-url-apple") 
        object.step2.likes = 7
        (async function ()
            user.save() // I also did error handling
        )()
        return
    
)

此方法工作正常,用户得到更新,但它不断抛出 ParallelSaveError 可能是因为我在代码的其他部分中的同一用户实例上并行调用 save() 函数。

所以我决定使用User.findOneAndUpdate() 方法,但是在使用mongodb 点符号$[<identifier>] 时我的查询一直失败,显然是因为我不知道如何正确使用它。

像这样:

let update = 
    "$set" :  
        "links.$[index1].$[index2].step2.likes" : 7,
    


let conditions = 
    arrayFilters : [
        "index1" : 1,
        "index2.step1" : "post-url-apple"
    ]


try 
    let result = await Users.findOneAndUpdate("_id" : "some_id", update, conditions)
    console.log(result)
 catch (err) 
    console.log(err)

出于所有充分的理由,我没有点击 catch 块,但更新同样不成功

如何使用findOneAndUpdate"step1": "post-url-apple" likes 字段更新为7?

谢谢。

【问题讨论】:

【参考方案1】:

arrayFilters 中,您应该定义应用于所有数组元素的条件,而不是索引

如果你确定,你总是更新外部数组的第二个数组元素(索引 = 1),那么你可以对外部数组使用点表示法,对于内部数组你可以使用数组过滤器来获取具有step1 = 'post-url-apple'的元素

您的代码可能看起来像这样

let update = 
    "$set" :  
        'links.1.$[item].step2.likes': 7 // here we used links.1 to access the second element of the outer array
    


let conditions = 
    arrayFilters : [
         'item.step1' : 'post-url-apple'  // item here is the element in the inner array that has step1 = post-url-apple
    ]

然后进行更新查询

希望对你有帮助

【讨论】:

我试过了,但仍然是同样奇怪的结果。显然问题出在我代码的其他部分,而不是您给出的逻辑。我会弄清楚代码的哪些部分导致了奇怪的行为。谢谢。 我已经通过某种方式跟踪并将索引传递给更新函数解决了这个问题,如下所示:'links.1.indexPassedToUpdateFunction.step2.likes': 7 where indexPassedToUpdateFunction = <Number>

以上是关于更新混合类型的猫鼬嵌套数组的主要内容,如果未能解决你的问题,请参考以下文章

嵌套数组的猫鼬$或条件

嵌套数组上的猫鼬聚合

用于多个对象数组的猫鼬嵌套模式

带有嵌套可选对象和必填字段的猫鼬模式

使用没有数组的嵌套文档为我的 JSON 定义有效的猫鼬模式?

嵌入式数组中的猫鼬更新对象