2016-07-30 98 views
0

我遇到了一些MongoDB查詢。我有一個簡單的結構來管理我的應用程序中的線程和消息。查詢未讀消息

{ 
    participants: [ 
    'u1,'u2' 
    ] 
    messages: [ 
    {text: 'some message', readBy: ['u1','u2']} 
    {text: 'some other message', readBy: ['u1']} 
    ] 
} 

作爲「U2」我想獲得查詢返回的該特定線程。這是我走了多遠,但只要一條消息被'u2'讀取,它就不會被返回,因爲其中一條消息已被'u2'讀取。

Threads.find(
     { 
      $and: [ 
       {'participants': this.userId}, 
       {'messages.readBy': {$nin: [this.userId]}}   
      ] 
     }    
    ) 

如何在不改變數據結構的情況下實現這一目標?

+0

什麼是預期你的查詢結果? – styvane

+0

最後,我需要對所有未讀的線程進行計數,即應該選擇至少有一條未讀消息的線程。我將使用此信息在網頁上顯示徽章,以便用戶知道有一些未讀郵件。來自SQL我沒有用來存儲非規範化的東西,所以我結束了給定的結構。需要注意的是,我正在使用Meteor,因此並非MongoDB支持的所有東西都是開箱即用的,並且是被動的。 – chris1069603

+0

如果你接受的答案有效,那麼有一個更好的方法來做到這一點。 – styvane

回答

0

您可以使用aggregation執行$unwind操作,該操作會將您的messages數組轉換爲Json對象,這將幫助您準確請求所需的項目。

下面的查詢會給你在哪裏「U2」正在參加,只有不被「U2」讀郵件記錄:

db.threads.aggregate([{ 
    $unwind: "$messages" 
}, { 
    $match: { 
     "participants": "u2", 
     "messages.readBy": { 
      $nin: ["u2"] 
     } 
    } 
}]); 

這會給你:

{ 
    "_id": ObjectId("579d0fc8733ac30906524be4"), 
    "participants": ["u1", "u2"], 
    "messages": { 
     "text": "some other message", 
     "readBy": ["u1"] 
    } 
} 
+0

我必須承認我以前從未使用聚合。非常感謝你提供了合格的答案。我要求不改變我的數據結構,但否定readBy(即使用unreadBy)將使我可以根據我的理解使用常規查詢嗎?您會推薦使用聚合還是通常更好地更改數據結構,以便我可以使用常規查詢? – chris1069603

+0

這取決於你。如果你使用'find'請求,你將不得不根據你的喜好解析結果,而使用聚合,mongoDB引擎爲你做。聚合需要花費更長的時間來執行,但你可以分組,創建字段,項目等......考慮到對於一個聚合,你可以有一個單一的數組,所有的新消息都是未讀的,而有了'find',你將不得不迭代結果並自己構建這個數組 –