当前位置: 首页 > 知识库问答 >
问题:

如何使用光标。MongoDB中使用Node的forEach()。js?

薛利
2023-03-14

我的数据库中有大量文档,我想知道如何浏览所有文档并更新它们,每个文档都有不同的值。

共有3个答案

刘乐童
2023-03-14

var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

MongoClient.connect('mongodb://localhost:27017/crunchbase', function(err, db) {

    assert.equal(err, null);
    console.log("Successfully connected to MongoDB.");

    var query = {
        "category_code": "biotech"
    };

    db.collection('companies').find(query).toArray(function(err, docs) {

        assert.equal(err, null);
        assert.notEqual(docs.length, 0);

        docs.forEach(function(doc) {
            console.log(doc.name + " is a " + doc.category_code + " company.");
        });

        db.close();

    });

});

请注意,调用。toArray正在使应用程序获取整个数据集。



var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

MongoClient.connect('mongodb://localhost:27017/crunchbase', function(err, db) {

    assert.equal(err, null);
    console.log("Successfully connected to MongoDB.");

    var query = {
        "category_code": "biotech"
    };

    var cursor = db.collection('companies').find(query);

    function(doc) {
        cursor.forEach(
                console.log(doc.name + " is a " + doc.category_code + " company.");
            },
            function(err) {
                assert.equal(err, null);
                return db.close();
            }
    );
});

请注意,find()返回的光标被分配给var cursor。使用这种方法,我们将数据流传输到应用程序,而不是一次获取内存中的所有数据并消耗数据find()可以立即创建游标,因为在我们尝试使用它提供的某些文档之前,它实际上不会向数据库发出请求。cursor的目的是描述我们的查询。第二个参数光标。forEach显示当驱动程序耗尽或发生错误时该怎么做。

在上述代码的初始版本中,强制数据库调用的是toArray()。这意味着我们需要所有文档,并希望它们位于数组中。

此外,MongoDB以批处理格式返回数据。下图显示了从游标(从应用程序)到MongoDB的请求

foreachtoArray更好,因为我们可以在文档进入时处理它们,直到我们到达结尾。将其与toArray进行对比-我们等待所有文档被检索并构建整个数组。这意味着我们没有从驱动程序和数据库系统一起工作以将结果批处理到您的应用程序这一事实中获得任何优势。批处理旨在在内存开销和执行时间方面提供效率。如果可以的话,在您的应用程序中利用它。

牧宁
2023-03-14

使用mongodb驱动程序和带有async/await的现代NodeJ,一个好的解决方案是使用next()

js prettyprint-override">const collection = db.collection('things')
const cursor = collection.find({
  bla: 42 // find all things where bla is 42
});
let document;
while ((document = await cursor.next())) {
  await collection.findOneAndUpdate({
    _id: document._id
  }, {
    $set: {
      blu: 43
    }
  });
}

这导致每次只需要在内存中存储一个文档,而不是在开始处理文档之前,将许多文档吸进内存的可接受答案。在“大量收藏”(根据问题)的情况下,这可能很重要。

如果文档很大,可以通过使用投影来进一步改进,以便只从数据库中获取所需的文档字段。

徐景明
2023-03-14

答案取决于你使用的驱动程序。我知道的所有MongoDB驱动程序都有游标。forEach()以某种方式实现。

以下是一些例子:

collection.find(query).forEach(function(doc) {
  // handle
}, function(err) {
  // done or error
});
db.collection.find(query).forEach(function(err, doc) {
  // handle
});
collection.find(query, { stream: true })
  .each(function(doc){
    // handle doc
  })
  .error(function(err){
    // handle error
  })
  .success(function(){
    // final callback
  });
collection.find(query).stream()
  .on('data', function(doc){
    // handle doc
  })
  .on('error', function(err){
    // handle error
  })
  .on('end', function(){
    // final callback
  });

. foreach回调中更新文档的唯一问题是您不知道何时更新所有文档。

要解决这个问题,您应该使用一些异步控制流解决方案。以下是一些选项:

  • 异步
  • promise(when.js,蓝鸟)

下面是一个使用async、使用其队列功能的示例:

var q = async.queue(function (doc, callback) {
  // code for your update
  collection.update({
    _id: doc._id
  }, {
    $set: {hi: 'there'}
  }, {
    w: 1
  }, callback);
}, Infinity);

var cursor = collection.find(query);
cursor.each(function(err, doc) {
  if (err) throw err;
  if (doc) q.push(doc); // dispatching doc to async.queue
});

q.drain = function() {
  if (cursor.isClosed()) {
    console.log('all items have been processed');
    db.close();
  }
}
 类似资料:
  • 我们使用MongoDB驱动程序中的某些函数来迭代游标,我们可以使用“hasNext()”和“getNext()”。但我们也可以使用简单PHP的foreach来迭代游标,而不必调用上述方法。 我的问题是,如果foreach是一个简单的PHP函数,它如何与MongoDB一起工作?它如何从游标中获取记录?它是在内部使用MongoDB的“cursor.forEach()”,还是在内部运行“hasNext(

  • 以下数据存储在我的收藏中 我为find和这是我从req获得的数据。我在这里提到的身体是一个疑问 我希望这个res.json应该只返回这两个文档 在mongoDB我们可以这样写 我想要nodejs中的解决方案,因为根据请求我们需要找到帮助我

  • 我正在使用meteor构建一个应用程序。js、MongoDB和我有一个关于游标的问题。forEach()。我想在每个forEach迭代开始时检查一些条件,如果不需要对元素执行操作,则跳过该元素,这样可以节省一些时间。 这是我的代码: 我知道我可以使用cursor.find()将游标转向数组。获取(),然后使用常规的for循环来迭代元素,并使用继续和正常中断,但我感兴趣的是,如果有类似的东西可以在f

  • 我正在做Liferay 6.2项目。在Liferay中,他们使用了Vaadin。当我点击一个按钮时,它会打开一个不同的iframe。我可以为所有功能编写代码。现在我想使用WebDriver将光标移动到iframe元素。因为当我将鼠标移动到iframe复选框之后,我的自动脚本就可以运行了。我想自动化一个脚本,将鼠标指针移动到元素。 我已经尝试了下面的代码,但它不起作用。 1) 使用动作移动元素: 2

  • 问题内容: 我的数据库中有大量的文档,我想知道如何浏览所有文档并更新它们,每个文档具有不同的值。 问题答案: 答案取决于您使用的驱动程序。我所知道的所有MongoDB驱动程序都以一种或另一种方式实现。 这里有些例子: mongojs 僧 猫鼬 在回调内部更新文档 在回调内部更新文档的唯一问题是您不知道何时更新所有文档。 要解决此问题,您应该使用一些异步控制流解决方案。以下是一些选项: 异步的 承诺

  • 我正在尝试创建一个发送邮件的应用程序。它获取用户输入(To、Subject、Message),单击表单按钮发送邮件,并将该邮件存储在mongodb上 前端 后端 > 架构 常量mongoose=require(“mongoose”); const UserSchema=new mongoose.schema({ 收件人:{type:String,},抄送:{type:String,},密件抄送:{