【问题标题】:Mongoose findOneAndUpdate on subdocument throw an validation error for ObjectId field子文档上的 Mongoose findOneAndUpdate 为 ObjectId 字段引发验证错误
【发布时间】:2020-10-01 19:14:35
【问题描述】:

我有一个基本的 ChatRoom 和 ChatMessage 架构。对于某种优化,ChatRoom 包含 lastMessage 属性作为 ChatMessage 类型的子文档。

export const ChatMessageSchema = new Schema({
  message: {
    type: String,
    required: true,
  },
  chatRoomId: {
    type: Schema.Types.ObjectId,
    required: true,
  },
  createdBy: {
    type: Schema.Types.ObjectId,
    required: true,
  },
  ...
}, {
  timestamps: true,
});

export const ChatRoomSchema = new Schema({
  membersIds: {
    type: [Schema.Types.ObjectId],
    required: true,
  },
  lastMessage: {
    type: ChatMessageSchema,
  },
  ...
}, {
  timestamps: true,
});

因此,每当创建新消息时,我都会尝试将 lastMessage 属性更新/替换为 findOneAndUpdate,就像这样。

const onChatMessagePosted = async ({ chatMessage, chatRoom }) => {
  // 1. Doesn't work, throw an "Path `chatRoomId` is required" error
  await ChatRoom.findOneAndUpdate(
    { _id: chatRoom._id },
    { $set: { lastMessage: chatMessage } },
    { new: true, runValidators: true },
  );

  // 2. It works
  chatRoom.set({ lastMessage: chatMessage });
  await chatRoom.save();

  // 3. It works too
  await ChatRoom.findOneAndUpdate(
    { _id: chatRoom._id },
    {
      $set: {
        'lastMessage._id': chatMessage._id,
        'lastMessage.chatRoomId': chatMessage.chatRoomId,
        'lastMessage.createdBy': chatMessage.createdBy,
        ...
      },
    },
    { new: true, runValidators: true },
  );
};

但由于某种原因,findOneAndUpdate 会为子文档字段抛出 path *propName* is required 错误。

"errors": {
  "lastMessage.chatRoomId": {
    "message": "Path `chatRoomId` is required.",
      "name": "ValidatorError",
      "properties": {
      "message": "Path `chatRoomId` is required.",
        "type": "required",
        "path": "chatRoomId",
        "value": "5f72f8666144a40bb15f368a"
    },
    "kind": "required",
      "path": "lastMessage.chatRoomId",
      "value": "5f72f8666144a40bb15f368a"
  },
  "lastMessage.createdBy": {
    "message": "Path `createdBy` is required.",
      "name": "ValidatorError",
      "properties": {
      "message": "Path `createdBy` is required.",
        "type": "required",
        "path": "createdBy",
        "value": "5ec65435dd1b860d9898609b"
    },
    "kind": "required",
      "path": "lastMessage.createdBy",
      "value": "5ec65435dd1b860d9898609b"
  }
},
"message": "Validation failed: lastMessage.chatRoomId: Path `chatRoomId` is required., lastMessage.createdBy: Path `createdBy` is required.",

令人困惑的部分是:

  • 它只抛出 type: Schema.Types.ObjectId 的字段(在此示例中为 lastMessage.message 道具通过验证);
  • mongoose save 方法不会抛出;
  • 它不会抛出正在使用子路径字段;

这是预期的猫鼬行为吗?如果有什么方法可以让它在不更新每个子文档字段或不保存方法的情况下工作?

谢谢!

【问题讨论】:

    标签: javascript mongoose mongoose-schema


    【解决方案1】:

    我猜你的问题来自Refs。您应该在 ChatRoomSchema 下添加 ChatMessageSchema 的引用。试试这个:

    chatMessage.js

    const mongoose = require('mongoose');
    const ChatMessageSchema = new Schema({
      message: {
        type: String,
        required: true,
      },
      chatRoomId: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
      },
      createdBy: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
      },
      ...
    }, {
      timestamps: true,
    });
    
    module.exports = mongoose.model('ChatMessage', ChatMessageSchema);
    

    聊天室.js

    const mongoose = require('mongoose');
    const ChatRoomSchema = new Schema({
      membersIds:[
          { type: mongoose.Schema.Types.ObjectId, ref: 'Member' }
        ],
      lastMessage: {
        type: mongoose.Schema.Types.ObjectId, ref: 'ChatMessage'
      },
      ...
    }, {
      timestamps: true,
    });
    module.exports = mongoose.model('ChatRoom', ChatRoomSchema);
    

    【讨论】:

    • 参考存在。我省略了它们以使代码示例更小。对不起,如果它让你感到困惑。另外,lastMessage 作为mongoose.Schema.Types.ObjectId 也没有问题。但就我而言,最好将其作为子文档。
    • 哎呀!好的,不用担心...你能告诉我 chatMessage 实例包含什么吗?
    猜你喜欢
    • 2020-05-22
    • 2014-09-11
    • 2017-08-13
    • 1970-01-01
    • 2016-04-25
    • 2020-11-19
    • 2019-06-03
    • 2014-09-15
    • 1970-01-01
    相关资源
    最近更新 更多