I have a array of messages messages = await ChatMessage.find()
, each message has replyTo
field which is defined as mongoose.Schema.Types.ObjectId
referencing ref:chattingMessage
document.
In db , replyTo stores references of two types of objects chattingMessage
and groupMessage
.
I want to populate replyTo
given it stores references to any type objects.
I implemented a function which populates all the messages which are referenced to chattingMessage
correctly but fails for groupMessage
. Here is the implementation.
// chattingMessage -> ChatMessage , groupMessage -> Message
async function populateReplyTo(messages) {
const populatedMessages = await Promise.all(messages.map(async (message) => {
if (message.replyTo) {
let replyMessage = await ChatMessage.findById(message.replyTo);
if (!replyMessage) replyMessage = await Message.findById(message.replyTo);
if (replyMessage) {
console.log('Found replyMessage:', replyMessage); // even though it console logs correctly
message.replyTo = replyMessage; // populated message is not assigned ??
} else {
console.log('No replyMessage found, assigning null');
message.replyTo = null;
}
}
if (message.replyTo && message.replyTo.sender) {
const replySender = await User.findById(message.replyTo.sender).select('_id username name');
if (replySender) {
message.replyTo.sender = replySender;
}
}
return message;
}));
console.log(populatedMessages)
return populatedMessages;
}
Here is logging of terminal
Found replyMessage: {
_id: new ObjectId("6714e824c212c22e48b96c89"),
sender: new ObjectId("6714e1acc212c22e48b92089"),
content: 'hii',
chat: new ObjectId("66604d0079ebab20eec4da73"),
replyTo: null,
status: 'Read',
messageType: 'ChatMessage',
deletedBy: [],
reports: [],
isDeleted: false,
attachments: [],
createdAt: 2024-10-20T11:23:16.998Z,
updatedAt: 2024-10-23T13:45:07.054Z,
__v: 0
} but populated one is not assigned , instead i only find reference in replyTo
[
{
_id: new ObjectId("671681fada25dcde60b63526"),
sender: new ObjectId("66dafffec77d3018b2b0ddb3"),
receiver: new ObjectId("6714e1acc212c22e48b92089"),
messageType: 'ChatMessage',
subscriptionRequestMessageAction: 'none',
message: 'where to start',
replyTo: new ObjectId("9023e824c212c22e48b96c89"), // why reference , even though I got the object logged above
status: 'Read',
deletedBy: [],
reports: [],
createdAt: 2024-10-21T16:31:54.514Z,
updatedAt: 2024-10-23T15:47:24.551Z,
__v: 0
}
]
clearly there is a problem in assignment. or Am I missing something. Any help is appreciated..
When you 'find' records from mongoose, they are not technically 'objects' in the JavaScript sense, but are 'Document' objects which are a mongoose specific class object. Directly changing these document objects can result in unexpected behavior.
You have to convert these documents into simple JS objects with one of these methods:
// if your `message` parameter is a 'Document', turn to objects.
message.toObject();
...
// probably should make the messages objects too
..... await ChatMessage.findById(message.replyTo).toObject();
// ^^^^^^^^^^ call this
Also, .toObject()
will make your queries faster too