0

This is my Schema:

const UserSchema = new mongoose.Schema({
  name: String,
  chats: [{
    lastMessage: String,
    lastUpdate: Date
  }]
});

Users Collection:

{
    "_id" : ObjectId("59987ef42aafc45204ee8bc3"),
    "name" : "Nico",
    "chats" : [ 
        {
            "_id" : ObjectId("599e58265cf2799c07925488")
            "lastMessage": "Test",
            "lastUpdate": "Test"

        }, 
        {
            "_id" : ObjectId("599e59218d4a52c7071f46df")
            "lastMessage": "Hi",
            "lastUpdate": "01/01/2017"
        }
    ]
},
{
    "_id" : ObjectId("59987ef42aafc45204ee8bc3"),
    "name" : "Lucas",
    "chats" : [  
        {
            "_id" : ObjectId("599e59218d4a52c7071f46df")
            "lastMessage": "Hi",
            "lastUpdate": "01/01/2017"
        }
    ]
}

I am trying to implement chat on my app. I am working on my function that will find and update (on each User document, on Chat array with ObjectID as equals being received by request) but i don't know whats the best approach and how to implement it.

The request to my endpoint will give me ChatID, UserID, and MessageBody. So my two approaches are: 1) Find by UserID, and then findAndUpdate on chat array prop where _idChat is equals as ChatID. 2) Find in Collection where _idChat is equals as ChatID and then update (this should retrieve me Users that have any object with ChatID and then update it)

This is what i am trying to implement (but having nothing being updated):

  static sendMessage(req: express.Request, res: express.Response) {

    const message = req.body.message;

    const idChat = req.body.idChat;

    const userIds = [req.body.sender, req.body.receiver];

    const updatePromises = [];

    userIds.forEach( userId => {
      updatePromises.push(
        UserDao['updateChat']
        (
          userId, idChat, 
{'$set': {'chats.$.lastMessage': message, 'chats.$.lastUpdate': new Date() }},

      );

    });

    Promise.all(updatePromises)
      .then(values => {
        return res.status(200).json(values);
    }).catch(reason => {
        return res.status(400).json(reason);
    });


userSchema.static('updateChat', (userId, chatId, query) => {
  return new Promise((resolve, reject) => {
    if (!_.isObject(query)) {
      return reject(new TypeError('query is not a valid Object.'));
    }

    if (!_.isString(userId)) {
      return reject(new TypeError('userId is not a valid String.'));
    }

    User
      .update(
        {_id: userId, 'chats._id': chatId},
        {$set: query},
        {upsert: true}
      ).exec((err, updated) => {
      err ? reject(err) : resolve(updated);
    });
  });
});

Thanks for your help!

Nicolas Taboada
  • 81
  • 1
  • 12

1 Answers1

0

How about this?

User.update({
            _id: request.userId,
            chats: {
                $elemMatch: {
                    _id: request.chatId
                }
            }
        }, {
            $set: {
                'chats.$.lastMessage': request.messageBody,
                'chats.$.lastUpdate': new Date()
            },
        },
        function(err) {
            // handle error
            console.log(err);
        }
    )

You are going to update the exact chat that matches your criteria because you'll be using the $ operator on the $set command.

  • I refactor as you said me but nothing happens userSchema.static('updateChat', (userId, chatId, query) => { return new Promise((resolve, reject) => { User .update( {_id: userId, chats: {$elemMatch: {_id: chatId}}}, {$set: query}, {upsert: true} ).exec((err, updated) => { err ? reject(err) : resolve(updated); }); }); }); – Nicolas Taboada Aug 26 '17 at 21:31