2014-09-26 66 views
1

我在MongoDB中使用MongoDb。在一個集合中,我正在保存事件。 在其他字段中,這些事件有一個開始和結束,在Mongodb中保存爲DatesMongoDb對日期範圍的唯一約束

events { 
    start: "Date1", 
    end: "Date2", 
    ... 
} 

當這個集合中插入新的文件,我需要禁止的文件插入其開始結束日期重疊alreay創建事件的約束。總之,我不希望任何事件共享相同的時間跨度。

問題:有沒有一種方法可以通過MongoDb處理這種約束,帶有某種唯一索引?我想不是,但如果我錯了,請糾正我!

如果不是:

問題我一定要檢查可能插入新的事件之前,重疊槽代碼?我是否需要設置某種寫鎖定,以便在檢查重疊並插入自己的事件之間,另一個用戶無法擠入事件?這在MongoDb中如何完成?

編輯

這是我想出了迄今爲止最好的方法,它實際上似乎工作不錯。

var input = getPostInput(); 

var query = {$and: [ 
    {start: {$lte: input.end}}, 
    {end: {$gte: input.start}} 
]}; 
db.events.findAndModify(query, {}, {$setOnInsert: input}, {new: true, upsert: true}, callback) 

它使用findAndModify作爲「findOrCreate」操作符的一種類型。 $setOnInsert僅當findAndModify未找到文檔時才添加POST輸入屬性,upsert: true說如果找不到文檔,它應該創建文檔。這兩個選項組合似乎創建了一個findOrCreate操作符。

EDIT更新時出現

問題(PUT)的事件。我不能重複使用上面的代碼,因爲它依賴於upsert$setOnInsert

編輯

@wdberkeley:

我還在這個主要問題掙扎:確保在一系列唯一性。我越想它,似乎「時間片陣列」可能是最不成問題的解決方案。例如,假設選擇5分鐘作爲最小時間段,並且平均預訂爲45分鐘。這將需要我保存9個號碼(可能爲date):timespan = [0,5,10,15,20,25,30,35,40],而不是兩個:start=0, end=45。 這是超過的四倍更多已保存數據平均預訂成功。 我不認爲是苛刻的,但你不覺得這是一個問題?或者當保存的數據是10次較大或100次較大時是否成爲問題?我意識到這也是相對於實際完成的預訂量的總和......

回答

1

在MongoDB中沒有一種簡單的方法可以做到這一點。我製作了一個替代選項,可以爲你工作。如果您的日期分散進行,就像這是用於預訂應用程序的用戶按天或小時保留對象一樣,那麼您可以使用唯一索引和多鍵索引的組合。例如,假設預訂是按天進行的。約翰Q儲備10月11日至10月14日,包容性。這就像是一年中的第281到284天 - 讓我們假設它正是那一天。保存保留字段作爲天的數組保留

> db.reservations.insert({ "span" : [ 281, 282, 283, 284 ] }) 

把唯一索引上span場。

> db.reservations.ensureIndex({ "span" : 1}, { "unique" : 1 }) 

現在你不能插入任何具有在其跨度那些日子裏的文件:

> db.reservations.insert({ "span" : [ 279, 280, 281, 282 ] }) 
// unique key error 

這可能會爲你工作了一些額外的調整要考慮到一年,或者可能是化合物唯一索引的一部分,以使時間段獨一無二,例如room_id酒店預訂。

另一種方法是協調客戶端的檢查。如果您有多個客戶端根本不相互通話,我想最好的辦法是在數據庫中共享一個「鎖定」:findAndModifylock集合中的一個文檔來檢查和獲取鎖定。一旦客戶端通過更改該文檔上的字段來鎖定該鎖定,則它可以檢查與查詢重疊的檢查,然後如果一切正常,則插入,然後再次通過更改鎖定文檔上的標誌來釋放鎖定。

+0

感謝您的回覆!請閱讀我對上述問題的編輯,看看我的解決方案是否是您最後一段中的意思。關於「鎖」,我不知道這意味着什麼,但是正如我所理解的,這個'findAndModify'將會被atomicaly完成,因此會「鎖定」這個集合,以便其他用戶不會在查詢和更新階段之間發生事件。 findAndModify操作。正確? – 2014-09-29 07:50:49

+0

可以說我把整個集合放在一個鎖上,而第二個用戶在第一個用戶擁有這個鎖的時候試圖保存一個事件。我應該如何迴應第二個用戶的嘗試?有錯誤信息? – 2014-09-29 09:32:54

+0

如果您要創建一個已創建的事件,那麼解決方案有什麼問題?我以爲你不想讓重疊?你也可以有一個單獨的更新路線。你可能會有第二個用戶的鎖重試循環,但我認爲你的更簡單的解決方案應該工作,所以它並不重要。 – wdberkeley 2014-09-29 14:52:11