MongoDB 中的游标是什么?

2024-05-04

我们对最终发生的事情感到困扰cursor not found exceptions对于一些 Morphia 查询asList http://mongodb.github.io/morphia/1.0/guides/querying/我找到了一个暗示SO https://stackoverflow.com/a/25201116/2092322,这可能会非常消耗内存。

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


文档defines https://docs.mongodb.org/manual/reference/glossary/#term-cursor光标为:

指向查询结果集的指针。客户端可以迭代游标来检索结果。默认情况下,游标在 10 分钟不活动后超时

但这并不是很能说明问题。也许定义一个可能会有所帮助batch对于查询结果,因为文件还指出 https://docs.mongodb.org/manual/core/cursors/#read-operations-cursors:

MongoDB服务器批量返回查询结果。批量大小不会超过最大 BSON 文档大小。对于大多数查询,第一批返回 101 个文档或刚好足以超过 1 MB 的文档。后续批量大小为 4 MB。 [...] 对于包含没有索引的排序操作的查询,服务器必须加载内存中的所有文档以在返回任何结果之前执行排序。

注意:在我们的查询中,我们根本不使用排序语句,但也不使用limit and offset.


这是之间的比较toArray()和 a 之后的光标find()在 Node.js MongoDB 驱动程序中。常用代码:

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() https://mongodb.github.io/node-mongodb-native/3.1/api/Cursor.html#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();
    });

根据文档,

调用者有责任确保有 有足够的内存来存储结果。

这是基于光标的方法,使用cursor.forEach() https://mongodb.github.io/node-mongodb-native/3.1/api/Cursor.html#forEach method:

    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文件并希望它们位于array.

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MongoDB 中的游标是什么? 的相关文章

随机推荐