如何使用猫鼬推送对象数组

时间:2020-07-20 21:09:43

标签: node.js mongodb mongoose

我试图使用内存中对象而不是$push命令来推入对象数组并保存更改,但它仅接受单个ObjectId。有办法吗?我的目标是提高效率,因为我已经将数据库对象存储在内存中。

模式:

const mongoose = require("mongoose");

const planejamentoSchema = new mongoose.Schema({
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "users",
  },
  dia: Date,
  receitas: [
    {
      _id: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "receitas",
      },
      nome: String,
      refeicao: String,
    },
  ],
});

const Planejamentos = mongoose.model("planejamentos", planejamentoSchema);

module.exports = Planejamentos;

使用$ push的路线

router.post("/", tokenValidation.checkToken, (req, res) => {
  let user = req.body.user;
  let dia = req.body.dia;

  const query = { user, dia };

  Planejamentos.findOne(query).exec((err, result) => {
      // AS YOU CAN SEE, I'VE GOT TO QUERY IT AGAIN 
      // INSTEAD OF JUST result.receitas.push(req.body.receitas)
      Planejamentos.updateMany(
        query,
        {
          $push: {
            receitas: { $each: req.body.receitas },
          },
        },
        (err, result) => {
            res.send(
              `Planejamento para ${query.user} em ${query.dia} atualizado com sucesso`
            );
        }
      );
  });
});

1 个答案:

答案 0 :(得分:1)

我认为使用$push仍然是最好的选择,因为它可以确保对Planejamentos文档进行原子更新。如果要更新内存中的阵列,则仍然必须在模型上执行.save()以确保将更新保存到数据库中。因此,无论哪种方式,您仍然必须深入数据库。

假设您只打算更新.findOne查询返回的文档,则可以通过直接调用.findOne的结果来更新,从而使更新查询更快,例如:

// ... 
Planejamentos.findOne(query).exec((err, result) => {
  // Call .update on the result directly
  result.update(
    {
      $push: {
        receitas: { $each: req.body.receitas },
      },
    },
    (udpateError, updateResult) => {
      res.send(
        `Planejamento para ${query.user} em ${query.dia} atualizado com sucesso`
      )
    }
  )
})
// ... 

与您当前拥有的.updateMany相对。

编辑
另外,如果您在Planejamentos模型上具有某些验证或中间件逻辑,则应更新内存中的数组,然后执行.save。请注意,您仍在访问数据库,实际上,在内部,猫鼬会将您对数组的更新转换为以下内容:

updateOne({ _id: <doc>._id }, { $push: { '$each': <Array update value> } } })

但是,这种方法将允许执行与模型关联的验证和中间件逻辑。更多详细信息here

如果您没有任何中间件或验证,则无需担心。