我有一个基本的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
道具通过验证)的字段抛出; save
方法抛出; 这是预期的猫鼬行为吗?如果有什么方法可以使它工作而无需更新每个子文档字段或没有保存方法呢?
谢谢!
答案 0 :(得分:0)
我想您的问题来自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);
chatRoom.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);