简体   繁体   English

返回插入的子文档

[英]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. 而是将$push .findOneAndUpdate()$push一起使用。 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: 这避免了.find()然后.save()模式的危险:

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. 另外,只需.slice(-1)[0]即可获取整个对象并返回它,或者如上所示过滤掉不需要的键。

Or even simply just return all the fields from the array element and $slice the array to return from the query from the server: 甚至只是简单地返回array元素中的所有字段并使用$slice数组从服务器的查询中返回:

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]
    );
  }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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