我是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”来处理。说明。

08-08 05:33
查看更多