mongoose 如何一次性更新大量文档?急。
在做 node 爬虫。
目前用的是 BulkWrite
:
const Book = mongoose.model('Book', bookSchema);
exports.saveAll = (from_en, books) => {
const bulkWrite = books.map(book => ({
replaceOne: {
filter: {
from_en,
originId: book.originId
},
replacement: book,
upsert: true
}
}))
return Book.bulkWrite(bulkWrite).catch(error => console.error(error))
}
然后发现,这么处理 11200 条数据耗时 600s:
catId: 82 from 5040 to 5600. crawl cost: 10.1min, dataTotal: 11200, upsertTotal: 11000, matchTotal: 200
mongodb is disonnected
mongodb: 603757.883ms
✨ Done in 604.47s.
这个该如何优化?
下面是部分爬虫逻辑的代码: while 内部的代码
机子性能:I7 6700HQ / 16G RAM
2018年04月28日17:36:55 更新
机子性能:阿里云 双核4G 云主机
现在用 eggjs 的定时任务代替 crontab 的 npm run start
,同时,更新的逻辑改为先查询已存在,存在则 replace 不存在则 insert。
但是现在发现, bulkWrite 的时间还是太长了。很容易出现后续的爬虫在更新时发生 connection fail 的错误。
{ MongoError: connection 12 to 127.0.0.1:27017 timed out
at Function.MongoError.create (/home/website/bookapp-web-test/node_modules/mongodb-core/lib/error.js:29:11)
at Socket.<anonymous> (/home/website/bookapp-web-test/node_modules/mongodb-core/lib/connection/connection.js:200:20)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at Socket.emit (events.js:208:7)
at Socket._onTimeout (net.js:420:8)
at ontimeout (timers.js:482:11)
at tryOnTimeout (timers.js:317:5)
at Timer.listOnTimeout (timers.js:277:5)
name: 'MongoError',
message: 'connection 12 to 127.0.0.1:27017 timed out' }
而且更新的时间也还是达到了 360000ms 之久。
saving catId: 83, result: total -> 11200 matched ->undefined, upsert ->undefined;cost: 366340ms
求助啊,真的急。
7 回复
replaceOne.filter里面的条件有索引吗?
@peasonlee
有。 from_en
是一个字符串。算吗?
redis先存着,后续再写入
来自酷炫的 CNodeMD
什么网页一个页面会有 11200 条数据。。。。。为啥不抓一个存一个。
这种情况不建议你用mongoose,直接用mongodb的3.0驱动,带有队列操作,而且还可以保证每条操作都成功
@MiYogurt 直接抓的 API 接口。
@xivistudios 就是用原生的 mongodb 驱动?