我正在使用mongoose从Mongodb查询一个非常大的列表
const chat_list = await chat_model.find({}).sort({uuid: 1}); // uuid is a index
const msg_list = await message_model.find({}, {content: 1, xxx}).sort({create_time: 1});// create_time is a index of message collection, time: t1
// chat_list length is around 2,000, msg_list length is around 90,000
compute(chat_list, msg_list); // time: t2
function compute(chat_list, msg_list) {
for (let i = 0, len = chat_list.length; i < len; i++) {
msg_list.filter(msg => msg.uuid === chat_list[i].uuid)
// consistent handling for every message
}
}
对于上述代码,t1约为46s,t2约为150s
t2真的太大了,太奇怪了。
然后我将这些列表缓存到本地json文件中,
const chat_list = require('./chat-list.json');
const msg_list = require('./msg-list.json');
compute(chat_list, msg_list); // time: t2
此时,t2大约为10s。
那么,问题来了,150秒对10秒,为什么?发生了什么?
我尝试使用worker在mongo查询后执行计算步骤,但时间仍然比10秒长得多
2条答案
按热度按时间moiiocjp1#
mongodb查询返回一个FindCursor,其中包含类似
.filter()
的数组方法,但结果不是一个Array。在过滤之前对游标使用
.toArray()
来处理mongodb结果集,这可能不会使整个过程更快,因为结果集仍然需要从mongodb中提取,但计算将是类似的。7bsow1i62#
马特打字比我快,所以建议的一些内容与这个答案的一部分一致。
我认为你在衡量和比较一些与你所期望和暗示的不同的东西。
您的期望是,一旦应用程序加载了所有数据,
compute()
函数大约需要10秒。(大部分)在你的第二次测试中得到了证明,除了这个测试包括从本地文件加载数据所花费的时间之外,您会看到有104
秒的差异(150 - 46
)之间的完成message_model.find()
和compute()
因此导致了问题。关键是成功地从
find
升级到message_model
并不等同于获得所有结果。一旦第一批结果准备就绪,find()
将返回一个游标对象。(显然大约94秒),这两个find()
操作需要进一步迭代游标并检索其余结果。t2
内部报告了额外的时间。@Matt建议,调用
.toArray()
应该会将时间移回您所期望的t1
。而且,由于.filter()
函数的歧义性,听起来可能更正确。还有另外两件事引起了我的注意。第一件是:为什么要在客户端检索所有这些数据并在那里进行筛选?也许您希望通过
$lookup
在数据库内部进行uuid
匹配?第二,这句话对我来说不太清楚:
create_time
本身在这里是一个字段,无论是否存在,您都需要对其进行升序排序。