Node.js中数据库Mongoose更新的最佳实践?

Node.js中数据库Mongoose更新的最佳实践?,node.js,performance,mongoose,code-readability,Node.js,Performance,Mongoose,Code Readability,假设我有以下模式: const mySchema = mongoose.Schema({ _id: mongoose.Schema.Types.ObjectId, date: Number, data: { field1 : Number, field2 : Number } }); 我想为具有“myAwesomeDate”的文档用“myAwesomeValue”更新字段2。我当前在异步/等待函数中的代码是: // V1 var

假设我有以下模式:

const mySchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    date: Number,
    data: {
        field1 : Number,
        field2 : Number
    }
});
我想为具有“myAwesomeDate”的文档用“myAwesomeValue”更新字段2。我当前在异步/等待函数中的代码是:

// V1
var myAwesomeDocument = await myModel.findOneAndUpdate(
    {date: myAwesomeDate},            //selector
    {$set: {                          //update
        'data.field2': myAwesomeValue
    }},
    {                                 //options
        upsert: false,
        new: true
    }
).exec();
此代码允许我使用更新的文档

如果我没有弄错的话,下面的代码具有相同的行为,但是要避免,因为它首先将文档加载到客户端(因此效率较低)():

现在,我想使用.doSomething()使我的代码更具可读性:

// V3 (any code mistake here ?)
var myAwesomeDocument = await myModel.findOne({date: myAwesomeDate})
    .set(
        {'data.field2': myAwesomeValue},
        {upsert: false, new: true}
    )
    .exec();
我的问题首先是关于效率,然后是关于代码可读性:

  • 有没有比V1更高效的代码
  • V3是否执行相同的更新?它和V1一样高效吗
  • 有没有一种更有效、更可读的方法来编写V3

谢谢你的回答

根据您提供的示例,效率最高的是v1

  • 引擎盖下的V1只会触发一个查询,mongo's
  • V2需要2次查询才能完成预期的更新。那么芬顿 updateOne
  • V3并没有做预期的事情,它只是做了findOne,而不是findOne 正在对找到的文档发出任何更新操作
V3的正确版本如下:

instance = await model
    .findOneAndUpdate({date})
    .set({'data.f2': f1},)
    .setOptions({new: true})
    .exec();
说明: Mongoose findOneAndUpdate返回a(检查示例)。然后,我们使用查询的方法来设置更新操作和选项

总之,您可以使用V1,也可以使用我提供的更新的V3,因为它们在后台使用相同的数据库调用

您始终可以使用来分析实际发送到数据库的查询

为了支持我上面所说的,下面是我用来运行测试的代码片段。您可以像这样调用它:

consturi='1〕mongodb://localhost:27017/test-萨夫;
const mongoose=require('mongoose');
常量计数=进程argv[2]?parseInt(process.argv[2]):1;
const debug=process.argv[3]='true';
施工日期=1234567;
常数f1=1;
常数f2=2;
let模型;
(异步函数(){
wait mongoose.connect(uri,{useNewUrlParser:true,useUnifiedTopology:true});
const schema=new mongoose.schema({
日期:年月日,
数据:{
f1:数字,
f2:编号,
}
});
model=mongoose.model('model',schema);
console.log(“####开始###”)
const doc1=等待轰炸(v1,轰炸计数);
控制台日志(doc1);
const doc2=等待轰炸(v2,轰炸计数);
控制台日志(doc2);
const doc3=等待轰炸(v3,轰炸计数);
控制台日志(doc3);
const doc4=等待轰炸(v4,轰炸计数);
控制台日志(doc4);
console.log(“#########”);
})().catch(error=>console.error(error)),然后(()=>process.exit(1));
异步函数v1(){
console.log(“####V1####\n”);
在每个之前等待();
console.time(“####V1###”);
让实例=wait model.findOneAndUpdate(
{date},
{
$set:{
“data.f2”:f1,
},
},
{
厄普塞特:错,
新:真的
}
).exec();
console.timeEnd(“####V1###”);
等待每一次();
返回实例;
}
异步函数v2(){
console.log(“####V2####\n”);
在每个之前等待();
console.time(“#####V2###”);
让instance=wait model.findOne({date}).exec();
instance.data.f2=f1;
instance=等待instance.save();
console.timeEnd(“#####V2###”);
等待每一次();
返回实例;
}
异步函数v3(){
console.log(“####V3####\n”);
console.time(“#####V3###”);
在每个之前等待();
让实例=等待模型
.findOne({date})
.设置(
{'data.f2':f1},
{upsert:false,new:true}
).exec();
console.timeEnd(“####V3###”);
等待每一次();
返回实例
}
异步函数v4(){
console.log(“####V4###\n”);
控制台。时间(“####V4###”);
在每个之前等待();
让实例=等待模型
.findOneAndUpdate({date})
.set({'data.f2':f1})
.setOptions({new:true})
.exec();
console.timeEnd(“#####V4###”);
等待每一次();
返回实例;
}
异步函数beforeach(){
等待新型号({
日期,
数据:{
f1,
f2,
},
}).save();
mongoose.set('debug',debug);
}
异步函数afterEach(){
mongoose.set('debug',debug);
wait model.deleteMany({});
}
异步函数轰击(f,次){
设x;
for(设i=0;i}
我认为第一个是最好的选择。在数据库上做任何事情都是一个很好的实践,以避免在客户端上操作时出现问题,对数据库的请求越少,效率就越高(速度和一致性)!现在我了解了V3中的错误,以及如何通过.appendSomething()符号构建查询!非常感谢您花时间准确回答!你收到赏金了吗?
instance = await model
    .findOneAndUpdate({date})
    .set({'data.f2': f1},)
    .setOptions({new: true})
    .exec();