Обновление mon goose вложенного массива смешанных типов - PullRequest
1 голос
/ 16 июня 2020

У меня есть схема mon goose смешанных типов, например:

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

What I хочу достичь, это обновить поле "step1": "post-url-apple" с 6 до likes из 7 Итак, я попытался использовать функцию 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, но обновление также не было успешным

Как мне добиться обновления поля "step1": "post-url-apple" likes до 7 с помощью findOneAndUpdate?

Спасибо .

1 Ответ

1 голос
/ 17 июня 2020

В arrayFilters вы должны определить условия, которые будут применяться ко всем элементам массива, а не к индексу

Если вы уверены, вы всегда обновляете второй элемент массива (index = 1) внешнего array, то вы можете использовать точечную нотацию для внешнего массива, а для внутреннего массива вы можете использовать фильтры массива, чтобы получить элемент, который имеет 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
    ]
}

затем выполните запрос на обновление

надеюсь, что это поможет

...