mongodb - MongoDB 中的游标是什么?

标签 mongodb mongodb-query database-cursor

我们为某些 Morphia 查询最终发生 cursor not found exceptions 而感到困扰 asList我找到了 hint on SO ,这可能会非常消耗内存。

现在我想了解更多关于背景的信息:有人能解释一下(用英语),游标(在 MongoDB 中)实际上是什么吗?为什么一直打开或者找不到?


文档 defines光标为:

A pointer to the result set of a query. Clients can iterate through a cursor to retrieve results. By default, cursors timeout after 10 minutes of inactivity

但这不是很能说明问题。为查询结果定义一个 batch 可能会有所帮助,因为 documentation also states :

The MongoDB server returns the query results in batches. Batch size will not exceed the maximum BSON document size. For most queries, the first batch returns 101 documents or just enough documents to exceed 1 megabyte. Subsequent batch size is 4 megabytes. [...] For queries that include a sort operation without an index, the server must load all the documents in memory to perform the sort before returning any results.

注意:在我们的查询中,我们根本不使用排序语句,也没有使用 limitoffset

最佳答案

下面是 Node.js MongoDB 驱动程序中 toArray()find() 之后的游标之间的比较。常用代码:

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.');

    const query = { category_code: "biotech" };

    // toArray() vs. cursor code goes here
});

这是 toArray()上一节中的代码。

    db.collection('companies').find(query).toArray(function (err, docs) {
        assert.equal(err, null);
        assert.notEqual(docs.length, 0);

        docs.forEach(doc => {
            console.log(`${doc.name} is a ${doc.category_code} company.`);
        });

        db.close();
    });

根据文档,

The caller is responsible for making sure that there is enough memory to store the results.

这是基于游标的方法,使用 cursor.forEach()方法:

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

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

使用 forEach() 方法,我们不是在内存中获取所有数据,而是将数据流式传输到我们的应用程序。 find() 会立即创建游标,因为在我们尝试使用它将提供的某些文档之前,它实际上并不向数据库发出请求。 cursor 的作用是描述我们的查询。 cursor.forEach 的第二个参数显示发生错误时要执行的操作。

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

请注意,MongoDB 会批量返回数据。下图显示了游标(从应用程序)到 MongoDB 的请求:

MongoDB cursor graphic

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

关于mongodb - MongoDB 中的游标是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51434829/

相关文章:

android - SQLite Android 数据库光标窗口分配 2048 kb 失败

mysql - 存储过程中的动态游标

python - 将pyodbc游标结果输出为python字典

mongodb - MongoError : can't find any special indices: 2d (needs index), 2dsphere(需要索引)

javascript - 对记录进行排序,然后在 MongoDB 中使用 updateMany 进行限制

mongodb - 是否可以在 Mongodb 中默认一个值,例如 $ifNull 但为空字符串?

node.js - 当前端取消请求时,如何让 Express.js 中止 MongoDB 请求?

mongodb 通配符匹配特定键的所有值

mongodb - 可以通过索引在 MongoDB 中使 $unwind 快速吗?

node.js - 并且偶尔会在 shell 和 Node native 驱动程序上产生错误的结果