【问题标题】:Update values by removing elements in the array with NodeJs and Mongoose通过使用 NodeJs 和 Mongoose 删除数组中的元素来更新值
【发布时间】:2022-12-17 14:59:27
【问题描述】:

我想实现的功能: 在前端,我有带有复选框的所有所有者的列表。添加的所有者已经被选中。如果我取消选中某些所有者 ID 并选中 2 个新所有者,我该如何实现,所以我删除未选中的所有者并添加新的“已检查”的。

我有一个用户模型:

const UserSchema = new mongoose.Schema({
  email: { type: String, required: true, min: 6, max: 255 },
  password: { type: String, required: true, min: 4, max: 1024 },
  role: { type: String, required: true, default: "User" },
  owners: [
    {
      type: Schema.Types.ObjectId,
      ref: "Owners",
      required: false,
    },
  ],
});

每个用户都有一组所有者

我使用此查询 PUT METHOD 将所有者添加到特定用户:

exports.addOwnerToUser = async (req: Request, res: Response) => {
  try {
    let ObjectID = require("mongodb").ObjectID;
    const mongoose = require("mongoose");

    const user = {
      email: req.body.email,
      ownerId: req.body.ownerId,
    };

        const updatedUser = await User.findOneAndUpdate(
  { _id: req.params.userId, owners: { $ne: req.body.ownerId } },
  { $push: { owners: { $each: req.body.ownerId } } },
  { new: true, useFindAndModify: false }
);

    res.status(201).json({ sucess: true, msg: "User updated sucessfully" });
  } catch (err) {
    res.status(404).json(err);
  }
};

2.)如果我在前端取消选中所有者,我该如何实现它,它会从所有者数组中删除?

【问题讨论】:

  • 您能否将标题调整为更具描述性?
  • 呃,对不起,我什至没有意识到我的头衔

标签: node.js mongoose


【解决方案1】:

你可以使用$pullAll

此操作从分数数组中删除您设置的值的所有实例

const updatedUser = await User.findOneAndUpdate(
  { _id: req.params.userId, owners: { $ne: req.body.ownerId } },
  { $pullAll: { owners: ["630367b3c8e06afa0339a609"] } },
);

你可以阅读文档HERE

【讨论】:

  • 我不能让它悲伤地工作:S
【解决方案2】:

$push 和 $pull 这两个操作在更新查询的单个属性中是不可能的,它将产生冲突错误,

我建议有3个选项,

  1. 如果 owners 数组限制为最多 10 个元素,则从前端获取所有者 ID 的整个数组并更新该数组,因此不需要推拉操作

  2. 执行 2 个单独的查询,第一个用于推送,第二个用于拉取元素

  3. 从MongoDB 4.2开始尝试update with aggregation pipeline查询,让我们通过一个例子来理解:

    考虑一个文档:

    [
      {
        _id: ObjectId("5a934e000102030405000000"),
        owners: [
          ObjectId("5a934e000102030405000000")
        ]
      }
    ]
    

    考虑输入变量:

    let _id = "5a934e000102030405000000";
    let addOwners = ["5a934e000102030405000001", "5a934e000102030405000002"];
    let removeOwners = ["5a934e000102030405000000"];
    

    让我们准备我们的查询,

    • 将更新部分包裹在数组括号中
    • $filter 迭代owners 数组的循环并删除removeOwners 数组变量中提供的id
    • $concatArrays 删除id后连接上面的过滤数组,并添加addOwners数组变量
    const updatedUser = await User.findOneAndUpdate(
      { _id: _id },
      [{
        $set: {
          owners: {
            $concatArrays: [
              {
                $filter: {
                  input: "$owners",
                  cond: { $not: { $in: ["$$this", removeOwners] } }
                }
              },
              addOwners
            ]
          }
        }
      }],
      { new: true }
    );
    

    Playground

【讨论】:

    【解决方案3】:

    我是这样解决的:

    exports.addOwnerToUser = async (req: Request, res: Response) => {
      try {
        let ObjectID = require("mongodb").ObjectID;
        const mongoose = require("mongoose");
    
        const user = {
          email: req.body.email,
          ownerId: req.body.ownerId,
        };
    
        const updatedUser = await User.findOneAndUpdate(
          { _id: req.params.userId },
          { $set: { owners: req.body.ownerId } },
          { arrayFilters: [{ owners: { $eq: user.ownerId } }], multi: true }
        );
    
        res.status(201).json({ sucess: true, msg: "User updated sucessfully" });
      } catch (err) {
        res.status(404).json(err);
      }
    };
    

    【讨论】:

    • 它如何在单个查询中对两个操作起作用?
    猜你喜欢
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    相关资源
    最近更新 更多