我是JavaScript的新手,终于把我的头转向异步编程。因此,虽然我可以说出为什么会遇到这个问题,但似乎无法找到解决方法...
我有一个字符串数组... [“ a”,“ b”,“ c”,“ a”]
我正在尝试将其以{word:count}的格式添加到mongo数据库中
array.forEach(callback)
function callback(w) {
collection.find({"word":w}).toArray(function(err, result) {
if (result.length == 0) {
//This means it's a new word
collection.insert({"word":w, "count":1}, function(err, res) {});
} else if (result.length == 1) {
//Word already exists in database
collection.update(....)
}
});
}
但是每次都会插入一个新词,计数永远不会更新。
它的发生是由于实现它的异步方式。
理想情况下,我想选择一个单词,检查它是否存在,插入/更新,然后查看下一个单词。
但是我不确定该怎么做。
我真的不希望“同步”执行此操作,只是想法很相似
最佳答案
您需要"upserts"代替。这基本上是一次操作中的“查找或创建”。您还希望以一种在循环之前尊重“写”操作的回调响应的方式来处理“循环”。但是,仅使用“批量”操作来处理它可能是合理的,因此实际的“写入”和“响应”仅发生一次:
collection.bulkWrite(
array.map(function(w) {
return {
"updateOne": {
"filter": { "word": w },
"update": {
"$inc": { "count": 1 }
},
"upsert": true
}
}
}),
function(err,result) {
// result contains BulkWriteResponse
}
)
$inc
运算符处理实际的增量,并且由于这是一个“ upsert”,因此如果在“ filter”中找不到匹配的文档,则会创建一个新文档。否则,现有的将被更新并“递增”。在“较大”的上下文中,理想情况下,您应从“流”中读取并为
.bulkWrite()
构建合理大小的“批量”操作的“批”。但是,如果您已经有了一个合理大小的数组,那么如图所示的单个“行内”上下文就没有问题。这里唯一“异步”的是实际的
.bulkWrite()
调用,因此在这种情况下,只有一点需要等待响应,而不是等待每个单独的操作。还有其他方法可以在“异步循环”中尊重每个“写入”的“回调”,但是对于此特定上下文,它很可能由单个
.bulkWrite()
调用以“批处理”为“ upsert”来处理。说明。