我有以下模型:
user :{
overall_stats: {
elo: {
type: Array,
default: {
date: new Date(),
ranking: 1000,
}
},
nrGames: {
...
},
nrWins: {
...
},
winRate: {
...
},
},
.
.
.
}
现在,我想将一个新条目:{ 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
}
)
}
错误在哪里?
答案 0 :(得分:1)
您的代码存在某些问题,请尝试以下代码:
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
}
}
注意:
$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
对象。以某种方式它可能不会引发任何错误或忽略$push: { elo: newElo }
。
同样,您也不能使用以下一项:
{
$push: {'overall_stats.elo' : newElo},
overall_stats : {
nrGames : numberOfGames,
nrWins : numberOfWins,
winRate : winRate
}
}
因为$push
会将元素推到{{1},所以您无法同时对$set
对象或其字段进行overall_stats
和$push
}}字段,与此同时elo
用新的$set
对象完全用新的overall_stats
对象替换了overall_stats
对象,因此从elo
中删除了overall_stats
字段!!至少对于不使用聚合管道的.update()
操作,它在.update
中不会那样工作,它将引发错误,因此,您需要像给定的那样指定每个需要更新的字段以上。
它不会更新,因为$push
是另一个$set
运算符,因此它不应位于$set
内。
您需要用async-await
包裹任何try-catch
以便更好地处理错误。
答案 1 :(得分:1)
$push
必须位于update参数的顶级,并且其他更新密钥将与之平行。因此,这将是正确的查询:
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
}
)
$ push的文档:https://docs.mongodb.com/manual/reference/operator/update/push/