2011-05-22 61 views
15

我有消息的集合:有什麼辦法可以自動更新MongoDB中的兩個集合?

{ 
    userid: ObjectId 
    total: int 
    unread: int 
} 

當我刪除「郵件」收藏,我也需要減少「總的消息:

{ 
    messageid: ObjectId 
    userid: ObjectId 
    message: string 
    isread: true|false 
} 

和消息的集合,每個用戶計數「在」計數「集合中,並且有條件地(如果」messages.isread「== false)減少」未讀「字段。

爲此,我需要先檢索消息,檢查其「isread」字段,然後更新計數。這些消息可能會被標記爲在這些操作之間進行讀取,然後我會錯誤地減少「未讀」計數。

有沒有一種方法可以根據一次拍攝中的其他收集結果有條件地更改某個收藏集中的某些內容?

回答

11

有很多答案在這裏,但我想,以填補在這裏所有的空白:

有什麼辦法可以以原子更新MongoDB中的兩個集合?

不是。兩個集合的原子更新實際上是一個事務。 MongoDB不支持跨集合甚至集合內的事務。

MongoDB提供several modifiers,它們在單個文檔上是原子的。所以你可以一次增加幾個不同的變量($inc)。儘管這裏有一些限制,但您無法對單個屬性執行兩種不同的操作。

有沒有辦法在一個鏡頭中基於其他集合的結果有條件地更改某個集合中的某些內容?

這裏有一些關於atomic updates的文檔。然而,你真正需要的是一個隊列和某種形式的two-phase commit或者你需要觸發器。

觸發器有not yet been implemented,所以它不是真的在你的情況下的選擇。

在這些操作之間可能會標記爲消息,然後我會錯誤地減少「未讀」計數。

在這一點上,你有幾個不同的策略,使其具有一定程度的一致性。坦率地說,根據你的描述,你可能想調查建立一個簡單的隊列來更新你的總數。

0

你可以用sql中的觸發器來做到這一點。但在蒙戈中,沒有觸發器。

您可以在文檔中的一個進行操作,並通過設置SafeMode.True

然後,如果沒有錯誤,則更新第二集中檢查LastErrorMessage上操作。

目前沒有辦法以原子方式做到這一點。

如果有,我會用在我的項目中。我也需要這個功能。

1

不,不幸的是這是不可能的。 MongoDB僅在單個文檔的範圍內支持​​。即使它們位於同一個集合中,也無法跨多個文檔執行事務操作。

4

您無法在同一時刻從兩個集合中刪除文檔。你可以做的是使用findAndModify()去除文檔,以便在刪除之前得到它的確切狀態。這會照顧你的未讀數問題。

1

MongoDB速度非常快,所以如果你的網站負載不高,你可以簡單地重新計算消息的總數和在每個請求上讀取的消息總數。只有在讀取索引。計數似乎非常快,即使是大量的數據。

實際上,您的總和未讀字段僅僅是緩存。你真的需要它嗎?

這裏有一個類似的問題一個問題:MongoDB: Calling Count() vs tracking counts in a collection

+0

這也是我的問題:)我的網站會有相當高的負載,而且我不想在每次需要時重新計算統計數據,所以我使用的是計數器集合。 – Andrey 2011-05-23 19:55:11

+0

如果您尚未這樣做,則應該對其進行配置。 – Maxence 2011-05-24 07:12:47

+0

即使沒有分析,我可以說cursor.count()總是比檢索一個數字慢得多,特別是在具有數億條記錄的集合上。 – Andrey 2011-05-24 11:57:37

相關問題