简体   繁体   中英

Return the inserted sub-document

Im building an app where i need to add messages as sub documents in a chat room. i need to return the data of the the sub document as soon as i insert it to the existing room. this is my code

  Room.findOne({ roomname: data.room }, (err, room) => {
    room.messages.push({ username: data.username, message: data.message });
    room.save((err, room) => {
      socket.broadcast.to(data.room).emit("new message", {
          username: room.messages.slice(-1).name,
          message: room.messages.slice(-1).message,
          createdat: room.messages.slice(-1).createdat
      });
    });
  });

So this the code i have used to retrieve last sub document. Is there any other way to achieve this?

room.messages.slice(-1).name

This is incorrect, demo below

[1,2,3].slice(-1)
// returns [3], not 3

You still have to use index

room.messages.slice(-1)[0].name
// or simply 
room.messages[room.messages.length - 1].name

Use .findOneAndUpdate() with $push instead. That way you only touch the database "once", and it also avoids the problem that something else possibly modifies the document and you end up overwriting that. This avoids the danger of the .find() then .save() pattern:

Room.findOneAndUpdate(
  { roomname: data.room },
  { "$push": { 
    "messages": { username: data.username, message: data.message }
  }},
  { "new": true },
  (err, room) => {
    let message = room.messages.slice(-1)[0];
    socket.broadcast.to(data.room).emit(
      "new message",
      Object.keys(message).filter(k => k !== "_id")
        .reduce((acc,curr) => Object.assign(acc,{ [curr]: message[curr] }),{})
    );
  }
);

Also, just .slice(-1)[0] to get the whole object and just return it, or filter out the unwanted keys just as shown above.

Or even simply just return all the fields from the array element and $slice the array to return from the query from the server:

Room.findOneAndUpdate(
  { roomname: data.room },
  { "$push": { 
    "messages": { username: data.username, message: data.message }
  }},
  { "new": true, "fields":  { "messages": { "$slice": -1 } } },
  (err, room) => {
    socket.broadcast.to(data.room).emit(
      "new message", room.messages[0]
    );
  }
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM