2017-07-08 83 views
0

在建立一個應用程序,我需要在聊天室中添加消息作爲子文檔。只要我將它插入現有房間,我需要立即返回子文檔的數據。這是我的代碼返回插入的子文檔

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

所以這是我用來檢索最後一個子文檔的代碼。有沒有其他方法可以實現這一點?

回答

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

倫 這給出了一個語法錯誤' 語法錯誤:在意外令牌* *(** err,room)=> {' – TRomesh

+0

@tromesh讓我想知道在哪裏一會兒。第二個例子是缺少一個'}'。糾正。在這裏爲我打字的權利,而不是外部編輯。 –

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