返回插入的子文档

时间:2017-07-08 05:45:21

标签: javascript node.js mongodb mongoose mongodb-query

我正在构建一个应用程序,我需要在聊天室中将消息添加为子文档。我需要在将其插入现有房间后立即返回子文档的数据。这是我的代码

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

所以这是我用来检索最后一个子文档的代码。还有其他方法可以达到这个目的吗?

2 个答案:

答案 0 :(得分:1)

room.messages.slice(-1).name

这是不正确的,下面的演示

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

您仍然需要使用索引

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

答案 1 :(得分:1)

使用.findOneAndUpdate()代替$push。这样你只需“触摸一次”数据库,它也避免了其他东西可能修改文件而你最终覆盖它的问题。这样可以避免.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] }),{})
    );
  }
);

另外,只需.slice(-1)[0]获取整个对象并返回它,或者如上所示过滤掉不需要的密钥。

或者甚至只是简单地返回数组元素中的所有字段,并从数组$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]
    );
  }
);