Невозможно создать объект * * * * для массива в мангусте - PullRequest
1 голос
/ 26 февраля 2020

У меня есть следующая модель:

user :{ 
    overall_stats: {
            elo: {
                type: Array,
                default: {
                    date: new Date(),
                    ranking: 1000,
                }
            },
            nrGames: {
                ...
            },
            nrWins: {
                ...
            },
            winRate: {
                ...
            },
    },
   .
   .
   .
}

Теперь я хочу добавить sh новую запись: { ranking: 1020, date: 2020-02-26T18:39:22.933Z } в массив elo. Я пробовал разные версии ниже, но свойство elo полностью исчезло после выполнения функции. nrGames и остальные обновлены правильно.

async function updateUserStatsAfterGameInDB(userId, newElo, numberOfGames, numberOfWins, winRate) {
    console.log(newElo);
    return await User.findOneAndUpdate(
        {
            _id: userId  // search query
        },
        {   
            overall_stats : {
                $push: {elo : newElo},
                nrGames : numberOfGames,
                nrWins : numberOfWins,
                winRate : winRate
            }
        },
        {
            new: true,                       // return updated doc
            runValidators: true,              // validate before update
            useFindAndModify: false
        }
    )
}

Где ошибка?

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

$push должен находиться на верхнем уровне в аргументе обновления, а остальные ваши ключи обновления будут параллельны ему. Так что это будет правильный запрос:

User.findOneAndUpdate(
        {
            _id: userId  // search query
        },
        {   
            $push: {'overall_stats.elo' : newElo},
            overall_stats : {
                nrGames : numberOfGames,
                nrWins : numberOfWins,
                winRate : winRate
            }
        },
        {
            new: true,                       // return updated doc
            runValidators: true,              // validate before update
            useFindAndModify: false
        }
    )

Документация для $ pu sh: https://docs.mongodb.com/manual/reference/operator/update/push/

1 голос
/ 26 февраля 2020

В вашем коде есть определенные проблемы, попробуйте следующий код:

async function updateUserStatsAfterGameInDB(userId, newElo, numberOfGames, numberOfWins, winRate) {
    console.log(newElo);
    try {
        return await User.findOneAndUpdate(
            {
                _id: userId  // search query
            },
            {
                $push: { 'overall_stats.elo': newElo },
                'overall_stats.nrGames': numberOfGames,
                'overall_stats.nrWins': numberOfWins,
                'overall_stats.winRate': winRate
            },
            {
                new: true,                       // return updated doc
                runValidators: true,              // validate before update
                useFindAndModify: false
            }
        )
    } catch (error) {
        // Do something on error scenarios
    }
}

Примечание:

  1. В пн goose вам не нужно явно используйте $set в обновлении, так как он сделает это за вас.

Итак, ваш код ниже:

{
    overall_stats: {
        $push: { elo: newElo },
        nrGames: numberOfGames,
        nrWins : numberOfWins,
        winRate : winRate
    }
}

преобразуется в:

{
    $set: {
        overall_stats: {
            $push: { elo: newElo },
            nrGames: numberOfGames,
            nrWins : numberOfWins,
            winRate : winRate
        }
    }
}

Таким образом, он заменяет overall_stats объект новым передаваемым объектом in. Каким-то образом это может не приводить к возникновению какой-либо ошибки или игнорированию $push: { elo: newElo }.

Аналогично, вы также не можете использовать ниже одного:

{   
            $push: {'overall_stats.elo' : newElo},
            overall_stats : {
                nrGames : numberOfGames,
                nrWins : numberOfWins,
                winRate : winRate
            }
  }

Потому что вы не можете сделать $push & $set в то же время для overall_stats объекта или его полей, так как $push перемещает элемент в поле elo, в то время как $set полностью заменяет overall_stats объект новым overall_stats объектом с только поле, переданное в запросе, поэтому удаляем поле elo из overall_stats !! Это не будет работать таким образом в .update(), по крайней мере, для .update операций, которые не используют конвейер агрегации, это вызовет ошибку, поэтому вам нужно указать каждое поле, которое необходимо обновить, как указано выше.

Это не обновление, потому что $push - это другой оператор, такой как $set, поэтому его не должно быть внутри $set.

Вам нужно обернуть любой async-await с try-catch для лучшей обработки ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...