我们为某些 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.
注意:在我们的查询中,我们根本不使用排序语句,也没有使用 limit
和 offset
。
最佳答案
下面是 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
的请求:
forEach
比 toArray
的扩展性更好,因为我们可以在文档进来时 处理文档,直到到达终点。将其与 toArray
对比 - 我们等待 ALL 检索文档并构建 entire 数组。这意味着我们没有从驱动程序和数据库系统协同工作以将结果批处理到您的应用程序这一事实中获得任何优势。批处理旨在提供内存开销和执行时间方面的效率。 如果可以,请在您的应用程序中利用它。
关于mongodb - MongoDB 中的游标是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51434829/