2011-05-16 37 views
0

數據樣本

{ 
    "Subject": "New thread" 
    "Messages": [ 
    { 
     "DateSent": "Mon, 16 May 2011 14:34:17 GMT -04:00", 
    }, 
    { 
     "DateSent": "Mon, 16 May 2011 14:59:57 GMT -04:00", 
    } 
    ], 
    "Participants": [ 
    { 
     "UserId": 2, 
     "LastReadMessageIndex": 0, 
    }, 
    { 
     "UserId": 1, 
     "LastReadMessageIndex": 1 
    } 
    ], 
} 

線程包含郵件列表和與會者名單時訪問列表的父。當參與者查看線程時,LastReadMessageIndex會更新爲消息的長度。

我想檢索給定參與者有未讀消息的線程數。我可以用我喜歡這個參與者的名單內$,此時操作:

db.MessageThreads.find({Participants: {$elemMatch: { UserId: 2, $where: {this.LastReadMessageIndex) < this.**parent**.Messages.length}}} }).count(); 

是否有可能訪問父對象?

回答

1

我認爲你在這裏遇到的問題是你正在配對$elemMatch$where。在$where的情況下,this的值應該是文檔本身。但是,它看起來像是說this是一個子文檔。

下面是一些示例代碼,你想要做什麼:

unread = function() { 
    for (var i in this.Participants) { 
     if (this.Participants[i].UserId == 2 && 
      this.Participants[i].LastReadMessageIndex < this.Messages.length) { 
       return true; 
     } 
    } 
    return false; 
} 

db.MessageThreads.find(unread) 

這裏唯一的問題是,我已經硬編碼的UserId2。如果您打算從其中一位客戶端驅動程序調用此功能,則必須在正確的位置注入該2

如果它看起來有點「哈克」,它是。您試圖比較單個文檔中的子文檔,而MongoDB在這方面效果並不好,而您的文檔結構並不能使這一點變得簡單。

你可能要考慮:

"Participants": { 
    "2": { "LastReadMessageIndex": 0 }, 
    "1": { "LastReadMessageIndex": 1 } 
} 

這種變化不會完全解決問題,但它確實讓他們查詢輕鬆了不少:

unread = function() { 
    return (this.Participants['2'].LastReadMessageIndex < 
    this.Messages.length); 
} 

如果這是一個重要的查詢,您可能需要考慮爲此過程構建一個Map/Reduce。

+0

謝謝。你是對的,改變結構是有道理的,而且更清潔。 – Dan 2011-05-17 14:18:14