3

So, I have a messageThread that has a reference to bunch of messages

var messageThreadSchema = new Schema({
    chatBetween: [{ type: Schema.Types.ObjectId, ref: 'User' }],
    messages: [{ type: Schema.Types.ObjectId, ref: 'Message' }],
    lastMessage: {type: String}
})

Accordingly, I have a message schema

var messageSchema = new Schema({
    sender: { type: Schema.Types.ObjectId, ref: 'User' },
    reciever: { type: Schema.Types.ObjectId, ref: 'User' },
    sentAt: { type: Date, default: Date.now },
    text: String,
    isRead: { type: Boolean, default: false }
})

I'm having a problem with updating message.isRead through messageThread.

I need to update isRead property of all messages that is inside messageThread


I've tried:

1.

 MessageThread.findByIdAndUpdate(req.body._id, {
  $set: {"messages.$.isRead": true} // I thought, maybe there is a typo and 
  "$set": {"messages.$.isRead": true} // tried too
  "$set": {"messages.$.isRead": "true"} // tried too
  })
  .populate({ path: "messages" })
  .exec((err, foundMessageThread) => {

});

2.

How to add update and delete object in Array Schema in Mongoose/MongoDB

MessageThread.update({'_id': req.body._id},
  {'$set': {
         "messages.$.isRead": true
   }},
      function(err,model) {
    if(err){
        console.log(err);
        return res.send(err);
    }
    return res.json(model);
});

3.

Then I decided to update isRead manually. I mean:

MessageThread.findById(req.body._id)
  .populate({ path: "messages" })
  .exec((err, foundMessageThread) => {
    var updatedMessage = foundMessageThread.messages.map(message=>{
        return {...message, isRead:true}
    })
    var newThread = {...foundMessageThread, 
    messages: [...foundMessageThread.messages, ...updatedMessage]}
    newThread.save()
  });

Of course it doesn't work in Node. So I had to redo everything using Object.assign() which made my code more messy.((

My question:

  1. Why my 1 and 2 methods are not working?
  2. Is there any easier method?
m_rd_n
  • 175
  • 2
  • 11
  • 1
    Can you pass `messageThread._id` and `message._id` to the function, find the `messageThread` then `findByIdAndUpdate` the `message`? – Chau Tran Jan 03 '18 at 18:28
  • 2
    You are trying to update a different collection from the collection you are running update on. Mongodb updates are only for data in single collection. Right way would be to manage the relationship separately and keep them in sync. This [should](https://stackoverflow.com/questions/32674280/removing-one-one-and-one-many-references-mongoose) clear things up for you. Its for removal but concept is similar. – s7vr Jan 03 '18 at 18:42
  • @ChauTran, you're right I could just search for `message._id` and change `isRead`, but I think it would negatively affect on performance. Because, there are might be a millions of messages that don't related to the user. Am I right? – m_rd_n Jan 03 '18 at 20:19
  • @Veeram, I think I could not get you. Could you clearify? When it comes to the example, it explains perfectly but I couldn't find reletionship with my case. I mean in my case I don't want to update `messageThread`, instead by populating it I want to get `message`s to update them. How could I update them without searching millions of messages? – m_rd_n Jan 03 '18 at 20:27
  • As your `messageSchema` shows, one `messageThread` only belongs to two Users communicating, doesn't it? You only `flagRead` to `message.receiver === currentUser.id && !message.isRead` and you can do the check on the Client side with another service to get the `currentUser`. I don't think it's gonna sabotage your performance, not enough to notice at the most. `messageThread`'s messages is an Array of `messageId` so you don't really NEED to do any modification here unless you implement Removing messages. – Chau Tran Jan 03 '18 at 20:33
  • One other thing to notice that Mongoose does have `Hooks` that you can use like `pre` and `post` so you can have `schema.pre('update', ...)` or `schema.post('update'...)` to modify other things relating to the message being updated accordingly. – Chau Tran Jan 03 '18 at 20:35
  • @ChauTran, yes `messageThread` belongs to two `Users` and it has one-many relationship with `message`. And I agree, I don't need to modify `messageThread`. What do you mean by `flagRead`? – m_rd_n Jan 03 '18 at 20:51
  • Just a method that I use in my application to flag a message as Read (in your case, set isRead to true). – Chau Tran Jan 03 '18 at 20:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162455/discussion-between-chau-tran-and-mardone). – Chau Tran Jan 03 '18 at 20:56

0 Answers0