node.js - 正在跳过多个 findOneAndUpdate 操作
问题描述
我有一个forEach
循环,我正在查询一个文档,做一些简单的数学计算,然后updating
是集合中的一个文档,然后继续下一次迭代。
问题是,很多时候随机一些UPDATE
操作不会更新文档。我不知道为什么会这样。lock
是不是因为
我曾尝试在手术前记录一些事情update
。数据都是正确的,但是当涉及到时update
,它根本不会随机更新。在 10 次迭代中,假设 8 次将正确工作
const name = "foo_game";
players.forEach(({ id, team, username }) => {
let updatedStats = {};
Users.findOne({ id }).then(existingPlayer => {
if (!existingPlayer) return;
const { stats } = existingPlayer;
const existingStats = stats[pug.name];
if (!existingStats) return;
const presentWins = existingStats.won || 0;
const presentLosses = existingStats.lost || 0;
updatedStats = {
...existingStats,
won:
team === winningTeam
? presentWins + 1
: changeWinner
? presentWins - 1
: presentWins,
lost:
team !== winningTeam
? presentLosses + 1
: changeWinner
? presentLosses - 1
: presentLosses,
};
// THE CALCULATIONS ARE ALL CORRECT TILL THIS POINT
// THE UPDATE WIILL RANDOMLY NOT WORK
Users.findOneAndUpdate(
{ id, server_id: serverId },
{
$set: {
username,
stats: { ...stats, [name]: updatedStats },
},
},
{
upsert: true,
}
).exec();
});
});
解决方案
基本上你在这里缺少的是异步操作findOne()
和findOneAndUpdate()
不能保证在你完成之前foreach()
完成。对于其中包含异步操作的循环,使用forEach()
不是一个很好的选择,但这里的另一个要点是它是完全没有必要的,因为 MongoDB 有更好的方法来执行此操作,并且在对服务器的一个请求中。
简而言之,您实际上想要提供一组指令 ,而不是“循环” bulkWrite()
:
let server_id = serverId; // Alias one of your variables or just change it's name
Users.bulkWrite(
players.map(({ id, team, username }) =>
({
"updateOne": {
"filter": { _id, server_id },
"update": {
"$set": { username },
"$inc": {
[`stats.${name}.won`]:
team === winningTeam ? 1 : changeWinner ? - 1 : 0,
[`stats.${name}.lost`]:
team !== winningTeam ? 1 : changeWinner ? - 1 : 0
}
},
"upsert": true
}
})
)
)
.then(() => /* whatever continuation here */ )
.catch(e => console.error(e))
因此,不是循环,而是在批量操作中为每个数组成员Array.map()
生成一个"updateOne"
语句并将其发送到服务器。当然,另一个变化是您根本不需要findOne()
读取现有值。您真正需要的是使用$inc
运算符来增加或减少当前值。在这里注意,如果当前在指定路径上没有记录任何内容,那么它将创建具有1/-1/0
由逻辑确定的任何值并传递给$inc
.
请注意,这实际上是您通常应该做的事情,除了避免不必要的异步调用循环之外,这里的主要事情是实际使用$inc
MongoDB 所具有的原子运算符。从数据库读取数据状态以进行更改是一种反模式,最好避免。
推荐阅读
- php - php切换到界面
- java - Eclipse 和 Tomcat 停止因错误而停止
- macos - 使用 cx freeze 在 python 上构建设置在 mac os 上会出错,但在 windows 上运行良好
- javascript - Javascript:查找较大的数组并返回较小和较大的数组
- c# - 在 C# 中循环密码检查器?
- javascript - 为什么 JavaScript 在创建的对象上返回 undefined?
- java - 斜体降价的正则表达式
- bash - 如何遍历目录中的所有文件,运行脚本,并将它们写入其他目录中的匹配文件
- redhat - 从 Red Hat Fuse 3.x 转换到 7.4 - JBI
- javascript - 有没有办法延迟执行 Axios 请求?