【问题标题】:Mongoose Update Field With the Item of the Another Field That is ArrayMongoose 使用数组的另一个字段的项目更新字段
【发布时间】:2021-05-05 02:52:29
【问题描述】:

我正在构建一个费用跟踪器应用程序,有一个用户集合,其中包含名称、金额、费用数组、收入数组等字段。

我的数据库是 Mongo Db with Mongoose,服务器是用 Express 写的。

这是填充值后的数据库截图

我正在尝试实现用户可以删除费用的路线,并且在删除费用后我想更新余额并使余额 = 余额 + 费用。我可以删除和支出但无法更新余额,因为我不知道如何从已删除的支出中检索余额


这里是删除路线:

router.delete("/", (req, res) => {
  const { UserID, ExpenseID } = req.query;
  const query = {
    $pull: {
      Expenses: { _id: ExpenseID },
    },
  };
  User.findByIdAndUpdate(UserID, query)
  
});

我想添加一个 Mongoose 方法,该方法将从收到的费用 ID 中获取费用金额并将其存储在一个变量中,在费用被删除后,我想调用一个方法来更新 Promise 中的用户余额.

这是我打算做的一个例子

// Deletes An Expense
router.delete("/", (req, res) => {
  const { UserID, ExpenseID } = req.query;
  const query = {
    $pull: {
      Expenses: { _id: ExpenseID },
    },
  };
  User.find({/*Some Query Which Will Return me The Provided Expense ID's Amount*/})
  User.findByIdAndUpdate(UserID, query)
  .then(() => {
    // Once I find and Remove the Expense, Now I would Like to Update the Users Balance
    // NewBalance = OldBalance + Expense ID's Amount Returned by the Find Method
    // Here I would Call another User.find method to update the Users Balance
  })
});

假设从上面的数据库快照中,我想删除费用(从 0 开始)第一个对象元素,名称:Uber Fare,我将向服务器发送 6091f725403c2e1b8c18dda3 的对象 ID,并且应该期望我的余额增加从 48495 到 49695

【问题讨论】:

  • 请分享代码而不是截图。
  • 我已将截图替换为代码@hhharsha36

标签: javascript node.js mongodb express mongoose


【解决方案1】:

你可以做的是:

  1. 使用UserID获取用户文档
  2. 使用ExpenseID查找费用
  3. 用费用金额更新Balance
  4. Expenses 数组中移除费用
  5. 保存用户文档
router.put("/", async (req, res) => {
  try {
    const { UserID, ExpenseID } = req.query;
    let user = await User.find({ _id: UserID });
    index = user.Expenses.findIndex((expense) => expense._id === ExpenseID);
    if (index != -1) {
      user.Balance += user.Expenses[index].Amount;
      user.Expenses.splice(index, 1);
    }
    await user.save();
    return res.status(200).json({ success: true, user: user });
  } catch (error) {
    return res.status(400).json({ success: false, error: error })
  }
});

注意:由于这是更新文档,我在路由器上配置了put方法而不是delete

【讨论】:

  • 我得到的响应是 { "success": false, "error": {} }
  • 你能把return res.status(400).json({ success: false, error: error })前面的console.log(error)加在这里吗?
【解决方案2】:

像这样为schema 创建一个static method

userSchema.statics.deleteExpenseUpdateBalance = async function (userID, expenseID) {
  const user = await this.findOne({ _id: userID });
  let userExpenses = user.Expenses;
  userExpenses.forEach((expense) => {
    if (expense._id === expenseID) {
      let amount = expense.Amount;
      let index = userExpenses.indexOf(expense);
      userExpenses.splice(index, 1);
      user.Balance += amount;
      return;
    }
  });

  user.save((err) => {
      if (err) {
          console.log(err)
      }
  });
};

在您的路由处理程序中访问它

router.delete("/", async (req, res) => {
  const { UserID, ExpenseID } = req.query;
  let result = await User.deleteExpenseUpdateBalance(UserID, ExpenseID)
});

static methodremove 费用和update 余额。 说明:static method 只是找到用户并遍历他们的Expenses 并删除所需的expense,而amount 只是添加到balance。最后调用user.save()方法保存所有文档。

注意:仅当您确定费用 ID 存在于 Expense 数组中时才使用此选项,否则您只需在静态方法中为此添加额外的检查

还将静态方法放在您创建 schemamodel 的文件中,在它们的两个创建之间,即在您创建 userSchema 之后和将其最终确定为 model 之前。

【讨论】:

  • 我必须在哪里创建静态方法?在与路由相同的文件中还是应该创建一个具有静态方法的单独文件?
  • 在您创建schema 的文件中创建static method。我在回答的最后一段中提到了具体情况。
  • 有没有办法可以实现上面相同的代码,但都在路由处理程序中,或者是否有必要创建一个静态方法并从处理程序中调用它?
  • 您可以将所有这些放在路由处理程序中。只需复制static method 中的所有逻辑并将其放入处理程序中。但最好用单独的文件来做。更容易更新、调试、阅读和管理所有内容。此外,创建 static method 允许您在需要时在其他地方使用它。
猜你喜欢
  • 2018-04-19
  • 2020-08-19
  • 2011-04-27
相关资源
最近更新 更多