首页 > 解决方案 > 更新数组 -NodeJs 中的字段

问题描述

我有这段代码循环遍历数据库中的所有用户,然后events根据id值查找特定的,如果有匹配项,它应该caption使用新的给定数据更新字段,

对于代码:

1- 搜索所有潜在用户 = OK

2 - 根据id= OK搜索和查找事件

3-更新字段caption= NOK

这是我的代码希望我提到了一切

router.post('/delete/:id',async (req, res) => {
 const eventId = req.params.id // this is the ID of the event
  User.find({}).lean(true).exec((err, users) => {
    let getTEvent = [];


    for (let i = 0; i < users.length; i++) {
      if (users[i].events && users[i].events.length) {

        for (let j = 0; j < users[i].events.length; j++) {
          if (users[i].events[j]._id === eventId) { 
            console.log('you event is :'+ eventId)  // this statement to verify if really got the correct ID or not
            users[i].events[j].caption ="deleted" // from here the problem
            users[i].save(err => {
              if (err) throw err;
              console.log("status changed saved");
              // Redirect back after the job is done.

            });

          }
        }
      }
    }


  });
  })

我得到的错误是users[i].save is not a function我不知道应该用什么替换它,

根据评论@whoami

router.post('/delete/:id', (req, res) =>
  User.findOneAndUpdate({
    "events._id": req.params.id
    },
    { $set: { "events.caption": "yesssss" }
  }, {upsert: true}, (err, user) => {
    if (err) {
      res.send('error updating ');
    } else {
      console.log(user);
      console.log(req.params.id)
  }
}));

下面是 mongoDb 和事件数据结构

在此处输入图像描述 在此处输入图像描述

希望我澄清了一切,

此致,

标签: node.jsmongodb

解决方案


实际问题:

.save()适用于猫鼬文档,但不适用于 javaScript 对象。在您的代码中,您已经.find()使用 : 将调用返回的猫鼬文档转换为 .Js 对象.lean(true)

.lean(true)用于将 mongoose 文档转换为 .Js 对象,以在代码中操作文档中的字段。

修复代码:

const mongoose = require('mongoose');

router.post("/delete/:id", async (req, res) => {
  const eventId = req.params.id; // this is the ID of the event
  await User.find({})
    .lean(true)
    .exec((err, users) => {
      let getTEvent = [];

      for (let i = 0; i < users.length; i++) {
        if (users[i].events && users[i].events.length) {
          for (let j = 0; j < users[i].events.length; j++) {
            if (users[i].events[j]._id === eventId) {
              console.log("you event is :" + eventId);
              users[i].events[j].caption = "deleted";
              users[i]._id = mongoose.Types.ObjectId(users[i]._id); // Converting `_id` string to `ObjectId()` to match with type of `_id` in DB
              let user = new User(users[i]); // Create a mongoose doc out of model
              user.save((err) => { // As we're passing `_id` in doc to `.save()` it will be an update call rather-than insert
                if (err) throw err;
                console.log("status changed saved");
                // Redirect back after the job is done.
              });
            }
          }
        }
      }
    });
});

正如我所提到的,这可以在没有阅读 docs/iteration/update 调用的额外过程的情况下完成。使用.updateOne().updateMany()$位置运算符一起可以在一个 DB 调用中完成:

 const mongoose = require('mongoose');
router.post("/delete/:id", async (req, res) => {
  const eventId = req.params.id; // this is the ID of the event
  /** We're using `.updateMany` with filter on `events._id` - 
   * So that all user docs which has `'events._id': eventId` will be updated,
   * If you've a particular user needs to be updated used `.updateOne()` with a filter to find that user document - filter kind of `userName` 
   * 
   * Both `.updateMany()` or `.update()` will return write result but not the docs,
   * if you need docs in response use `.findOneAndUpdate` or `.findAndModify()`
   */

   /** `$` helps to update particular object's caption field in `events` array (Object where `{ 'events._id': eventId }` ) */

   await User.updateMany({ 'events._id': eventId },{$set : {'events.$.caption': 'deleted'}}).exec((err)=>{
    if (err) throw err;
    console.log("status changed saved");
    // Redirect back after the job is done.
  })
});

参考: 更新文档


推荐阅读