【问题标题】:What causes Mongoose `updateMany` to return `{ acknowledged: false }`是什么导致 Mongoose `updateMany` 返回 `{ 承认:false }`
【发布时间】:2021-12-04 02:01:23
【问题描述】:

我正在尝试使用 MongoDB 为 Express 应用设置通知。

我有一个 API 端点,我在 MongoDB 中的 readBy 字段中 $push 一个用户的 ID,以便在检索到用户的通知后将其“标记”为已读。当我向此端点发出请求时,它会返回 200 及其通知,但不会对 MongoDB 中的通知文档进行任何更新。 console.log回调中的查询响应给了我{ acknowledged: false }。根据Mongoose docsacknowledgedBoolean indicating everything went smoothly,但是关于acknowledged 是什么以及在查询/写入过程中的哪个时间点导致它发生的信息很少。由于它没有返回任何错误,我找不到解决问题的方法。

有人能解释一下acknowledged: false 到底是什么,通常是什么原因导致它,以及为什么它不会引发错误。

型号:

const notificationSchema = new Schema({
  timestamp: {
    type: Date,
    required: true
  },
  type: {
    type: String,
    required: true,
    enum: [
      'newCustomer',
      'contractSigned',
      'invoicePaid',
      'warrantyExp',
      'assignedProject'
    ]
  },
  recipients: [{
    type: Schema.Types.ObjectId,
    ref: 'Employee',
    required: true,
  }],
  customer: {
    type: Schema.Types.ObjectId,
    ref: 'Customer',
    required: true,
  },
  readBy: [{
    type: String
  }],
  uuid: {
    type: String,
    default: uuid.v4,
    immutable: true,
    required: true,
  },
  company: {
    type: Schema.Types.ObjectId, ref: 'Company'
  }
});

路线:

router.get("/notification/all", withAuth, async (req, res) => {
  const FOURTEEN_DAYS = new Date().setDate(new Date().getDate() + 14);
  try {
    const { uuid, userId } = req.loggedInUser;

    // Fetch notifications that have the user as a recipient.
    Notification.find({
      recipients: userId,
    })
      .populate("customer")
      .exec((err, notifs) => {
        if (err)
          return res.status(500).json({
            success: false,
            message: "Error: Failed to retrieve notifications.",
          });

        const result = [];
        const notifIds = [];

        for (const notif of notifs) {
          // Filter notif
          result.push({
            timestamp: notif.timestamp,
            customer: notif.customer,
            type: notif.type,
            read: notif.readBy.includes(uuid),
          });
          // Add the user as read
          notifIds.push(notif.uuid);
        }

        console.log(notifIds);

        /* THIS RETURNS ACKNOWLEDGED: FALSE */         
        // Write to DB that user has read these notifications
        Notification.updateMany(
          { uuid: { $in: notifIds } },
          { $push: { readBy: uuid } },
          (err, resultUpdate) => {
            if (err)
              return res.status(500).json({
                success: false,
                message:
                  "Error: Failed to add check off notifications as read.",
              });

            console.log(resultUpdate);

            // Delete notifications past 14 days and has been read by all recipients
            Notification.deleteMany(
              {
                timestamp: { $gte: FOURTEEN_DAYS },
                $expr: {
                  $eq: [{ $size: "$readBy" }, { $size: "$recipients" }],
                },
              },
              (err) => {
                if (err)
                  return res.status(500).json({
                    success: false,
                    message: "Error: Failed to delete old notifications.",
                  });

                return res.status(200).json({
                  success: true,
                  notifications: result,
                  message: "Fetched notifications",
                });
              }
            );
          }
        );
      });
  } catch (err) {
    res.status(500).json({ success: false, message: err.toString() });
  }
});

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    所以事实证明这个问题与写关注无关。 acknowledged: false 被返回,因为我们试图 $push 的值是 undefined。所以本质上 Mongoose 拒绝写入 undefined 值,但不会因为输入值未定义而引发错误。把它放在这里以防其他人遇到这个问题。

    【讨论】:

    • 非常感谢,这正是我的问题。原来我忘了“等待”我的承诺 xD
    【解决方案2】:

    来自docs

    该方法返回一个包含以下内容的文档:

    • 如果操作运行时带有写入问题,则布尔值被确认为 true;如果写入问题被禁用,则布尔值被确认为 false
    • matchedCount 包含匹配文档的数量
    • modifiedCount 包含修改文档的数量
    • upsertedId 包含更新插入文档的 _id

    【讨论】:

    • 所以如果我做对了,acknowledged 为假意味着它无法写入数据库,对吧?为什么 MongoDB 使用它来传达错误而不是像其他 MongoErrors 那样引发异常?您是否碰巧知道解决 acknowledgedfalse 的案例的任何良好做法?
    • 不,它并不表示操作的成功或失败。查看 mongodb 文档中的 write concern 和 mongoose 中的 writeConcern 选项。如果您没有请求 w:1 或更高级别的写关注,那么确认将是错误的。
    • 感谢@Joe 的跟进。 writeConcern 对我来说是全新的,所以我很抱歉所有这些问题。通读后,我是否需要在选项中的事务级别确认写入事务 (updateMany)?我想知道为什么我从未在我的其他项目或任何其他端点中遇到过这种情况。这是否与 MongoDB 5.0 中的默认 ww: 'majority' 而不是 w: 1 这一事实有关?
    • unacknowledged 表示w: 0,即指示服务器不确认操作,这将使其非常快但无法处理失败。
    猜你喜欢
    • 1970-01-01
    • 2018-06-03
    • 2011-05-17
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 2012-10-16
    相关资源
    最近更新 更多