2013-07-30 87 views
0

是的標題可能聽起來很愚蠢,但我有兩個集合:訪問者和聊天。聊天有訪客,訪客有很多聊天。我定期刪除last_activity字段低於x天的訪問者,但我不想刪除有聊天的訪問者,所以我需要一種方法來delete from visitors where last_activity < days_unix_milliseconds and _id not in(select visitor_id from chats)Mongodb刪除沒有關聯文檔的文檔

我有第一部分的工作代碼(last活動),需要第二次幫助:

Visitors.remove({ 
    last_update: { 
     $lt: (new Date()).getTime() - 3600000 * 24 * 7 
    } 
}, function(error){ 

}); 
+1

denormalize .... – mkoryak

回答

6

我的建議是改變你的模式,這樣你就可以這樣做只有一個查詢。在這種情況下,我可能會保留每個visitor的字段,告訴你它有多少聊天。你可以簡單的增加這個每次用戶啓動一個聊天時間:

db.visitors.update({ visitor_id: XXX }, { $inc: { 'chat_count': 1 } }); 

而當它結束:

db.visitors.update({ visitor_id: XXX }, { $inc: { 'chat_count': -1 } }); 

然後去除沒有聊天所有遊客很簡單,只要:

db.visitors.remove({ last_activity: { $lt: XXX }, chat_count: { $lt: 1 } }); 
2

所以每個聊天有場visitor_id和要刪除唯一訪問者的_id沒有出現在聊天一個visitor_id?您必須循環訪問所有訪問者,併爲每個訪問者檢查last_activity,如果它是刪除的候選人,請與該訪問者的_id聊天時執行find()。如果它沒有文件,您可以刪除該訪客。

當您遍歷所有訪問者時,您使用MongoDB遊標(find()的結果)執行此操作。遊標以這樣的方式實現,即您可以在對其進行迭代時安全地從基礎集合中刪除文檔。

訣竅是,你不會試圖在一個單一的remove()調用中表達所有內容。迭代,檢查和刪除是迭代的一部分。您要確保循環內的find()速度非常快,只需將visitor_id上的索引添加到聊天記錄收集中即可。

+0

所有這一切都是真實的,因爲MongoDB中沒有JOIN。你不能選擇在哪裏。您可以選擇,選擇並循環代碼。 – ixe013

+0

他建議的SQL版本也沒有使用任何連接。 – drmirror

+0

'不在選擇中'是一個連接。它可能不是有效的SQL,但它是查詢的概念,服務器需要讀取兩個表以生成結果。是否使用'JOIN'關鍵字是不相關的。 Mongo查詢在一個集合上(或者如果你願意的話)。你不能通過設計讓mongo鏈接兩個集合。 – ixe013