Javascript 猫鼬:findOneAndUpdate~500k文档
由于我想更新整个文档集合,有些可能存在,有些没有500k条目的文档,所以我循环使用来自CSV的纯JS对象,并通过findOneAndUpdate方法更新所有文档 下面是一个简化的JS代码:Javascript 猫鼬:findOneAndUpdate~500k文档,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,由于我想更新整个文档集合,有些可能存在,有些没有500k条目的文档,所以我循环使用来自CSV的纯JS对象,并通过findOneAndUpdate方法更新所有文档 下面是一个简化的JS代码: const mongoose = require("mongoose"); const { mongoUrl } = require("../config.js"); const MyModel = require("../models/MyModel"); async function run() {
const mongoose = require("mongoose");
const { mongoUrl } = require("../config.js");
const MyModel = require("../models/MyModel");
async function run() {
mongoose.set("useCreateIndex", true);
await mongoose.connect(mongoUrl, { useNewUrlParser: true });
const r = [/* */]; // <-- Something with 500k objects
const total = r.length;
for (let i in r) {
const e = r[i];
e.REF = e.REF.trim();
await MyModel.findOneAndUpdate({ REF: e.REF }, e, { upsert: true, new: true });
if (i % 500 === 0) {
console.log((i / total) * 100 + "%");
}
}
}
run();
第一次插入的速度超过每秒500次,但当它达到25%时,对于500个条目,它开始非常慢10秒或更长时间。我想冷冻会慢一点吗?接近80%
有没有更好的方法来做这样的事情?我怎样才能加快速度
我的意思是,它只有50万个实体,有很多属性,但我认为这并不重要。我可以想到两种更有效的方法 确保在REF上有索引 创建批处理更新,而不是逐个等待
有两种方法可以让你更有效地做到这一点,我可以想到 确保在REF上有索引 创建批处理更新,而不是逐个等待
将评论作为答案发布:
你有吗?否则,数据库将必须扫描整个集合,以确定是否存在具有相同参考的模型。将注释发布为答案:
你有吗?否则,数据库将不得不扫描整个集合,以确定是否存在具有相同引用的模型。我曾经为数据库模型迁移执行过此类操作,我发现。bulkWrite在这里确实起到了作用。我要做的是:
const mongoose = require("mongoose");
const { mongoUrl } = require("../config.js");
const MyModel = require("../models/MyModel");
async function run() {
mongoose.set("useCreateIndex", true);
await mongoose.connect(mongoUrl, { useNewUrlParser: true });
const r = [/* */]; // <-- Something with 500k objects
const total = r.length;
// Set empty array of bulk write operations
let bulkWriteOps = [];
for (let i in r) {
const e = r[i];
e.REF = e.REF.trim();
/* As every update operation is different because it depends on the iteration
variable, you have to push each element individually */
bulkWriteOps.push({
updateOne: {
'filter': { REF: e.REF },
'update': e,
'upsert': true
// As you are not using the result of the update, you don't need the new: true flag
}
})
if (i % 500 === 0) {
console.log((i / total) * 100 + "%");
}
}
}
if (bulkWriteOps.length) await MyModel.bulkWrite(bulkWriteOps)
run();
在您的情况下,在每次迭代中,您都在等待文档被查询和更新。大容量写操作旨在避免此类情况,并让DB在幕后完成繁重的工作
如果您想更深入地阅读本主题,请看,这里它告诉您有关批处理大小和操作顺序的信息
希望这能在某种程度上帮助您解决您的问题我曾经为数据库模型迁移做过此类操作,我发现了这一点。bulkWrite在这里确实起到了作用。我要做的是:
const mongoose = require("mongoose");
const { mongoUrl } = require("../config.js");
const MyModel = require("../models/MyModel");
async function run() {
mongoose.set("useCreateIndex", true);
await mongoose.connect(mongoUrl, { useNewUrlParser: true });
const r = [/* */]; // <-- Something with 500k objects
const total = r.length;
// Set empty array of bulk write operations
let bulkWriteOps = [];
for (let i in r) {
const e = r[i];
e.REF = e.REF.trim();
/* As every update operation is different because it depends on the iteration
variable, you have to push each element individually */
bulkWriteOps.push({
updateOne: {
'filter': { REF: e.REF },
'update': e,
'upsert': true
// As you are not using the result of the update, you don't need the new: true flag
}
})
if (i % 500 === 0) {
console.log((i / total) * 100 + "%");
}
}
}
if (bulkWriteOps.length) await MyModel.bulkWrite(bulkWriteOps)
run();
在您的情况下,在每次迭代中,您都在等待文档被查询和更新。大容量写操作旨在避免此类情况,并让DB在幕后完成繁重的工作
如果您想更深入地阅读本主题,请看,这里它告诉您有关批处理大小和操作顺序的信息
希望这能对你的问题有所帮助你有参考索引吗?否则,数据库将不得不扫描整个集合,以确定是否存在具有相同引用的模型。@AKX Yes,of cou。。。哼完成。很高兴我能帮忙!我相信如果你想要更高的性能,它会更完整,所以你可能想看看它。我提供了一个.bulkWrite的例子,如果你需要的话。你在REF上有索引吗?否则,数据库将不得不扫描整个集合,以确定是否存在具有相同引用的模型。@AKX Yes,of cou。。。哼完成。很高兴我能帮忙!我相信如果你想要更高的性能,它会更完整,所以你可能想看看它。如果需要,我提供了一个.bulkWrite的示例。