2010-12-05 71 views
8

我有一個lists集合,其中每個文檔有一個數組membersmembers數組的每個元素都是一個帶有email屬性的文檔,創建date屬性以及一些其他元。我在members.email上有一個唯一索引,以防止同一個電子郵件被同一個列表兩次輸入,但我想保留原始date的值。不幸的是,$addToSet$push似乎都沒有這樣做。

實施例使用$推:

$lists->update(array('_id' => $list['_id'], 'members.email' => array('$ne' => $email)), array('$push' => array('members' => array(
    'email' => $email, 
    'date' => new MongoDate(), 
    // etc. 
)))); 

並與$ addToSet:

$lists->update(array('_id' => $list['_id']), array('$addToSet' => array('members' => array(
    'email' => $email, 
    'date' => new MongoDate(), 
    // etc. 
)))); 

兩個例子都用新的更換整個嵌入的文檔由於(I假設)獨特的date值。如果members.email還不存在,或者我需要在兩個命令中執行此操作,是否可以只有$push「成員」文檔?

或者,將members置於其自己的集合中,類似parent_list的屬性會更好的可擴展性嗎?

回答

1

爲什麼不在你存儲的地方存放list_id,電子郵件,added_date 然後,你將在2個鍵list_id和email上創建一個唯一的索引。這將阻止插入 的記錄具有相同的list_id和電子郵件地址

不會有嵌入式文檔。你仍然可以使用find()list_id

0

是的,這是可能的。查看mongoDB advanced queries部分中的$ exists操作符。將$ exists條件編碼到where語句中,僅在成員電子郵件不存在時更新。

+1

我幾乎可以肯定存在$是不是我要找的解決方案。 – Kevin 2010-12-06 02:17:28

5

根據我的經驗,您不能「$ push」或「$ addToSet」的原因是因爲您的目標「成員」可能是一個嵌入對象(或在其創建後轉換爲一個對象)。您只能在嵌入式陣列上使用$ push,$ pushAll,$ addToSet ...

對我們來說不幸的是,PHP開發人員遊標查詢總是以數組的形式返回數據,這是檢查「成員」是一個數組或對象,是在mongo shell中運行find(),並在結果中查找捲曲/方括號(「{}」或「[]」)。

希望這會有所幫助。

0

IIUC,嘗試使用Upsert來更新嵌入式文檔(如果是這樣的)或插入它(如果沒有)。請參閱this

至於你關於可伸縮性的第二個問題,它真正的案例依賴性......將文檔嵌入到父級需要更強的更新和更大的數據提取,但是減少提取查詢的數量。

1

使用$ne查詢condiction具有相同的電子郵件的成員來過濾文件:

$lists->update(array('_id' => $list['_id'], 
        'members.email' => array('$ne' => $email)), 
       array('$addToSet' => array('members' => array(
        'email' => $email, 
        'date' => new MongoDate(), 
         // etc. 
)))); 
相關問題