我用的Mnesia來存儲用戶的數據和記錄的結構類似於袋限制mnesia中某個鍵下的記錄數的慣用方式是什麼?
{用戶名,字段1,filed2,時間戳}
爲了不讓數據庫爆炸,我想設置一個限制屬於某個用戶的記錄數,例如,如果用戶的記錄數達到500,則在插入新記錄之前刪除具有最早時間戳的記錄。
有沒有一種有效的方法來做到這一點?
在此先感謝。
我用的Mnesia來存儲用戶的數據和記錄的結構類似於袋限制mnesia中某個鍵下的記錄數的慣用方式是什麼?
{用戶名,字段1,filed2,時間戳}
爲了不讓數據庫爆炸,我想設置一個限制屬於某個用戶的記錄數,例如,如果用戶的記錄數達到500,則在插入新記錄之前刪除具有最早時間戳的記錄。
有沒有一種有效的方法來做到這一點?
在此先感謝。
我提供了兩種可能性。一個適合你的設計,一個引入你的記錄定義的小改動。看哪一個最適合您的需求。下面的第一個是在你的設計中工作。
-record(user,{username,field1,field2,timestamp}). %% execute the function below in a mnesia transaction insert(#user{username = U,timestamp = _T} = User)-> case mnesia:read({user,U}) of [] -> mnesia:write(User); AllHere -> case length(AllHere) == 500 of false -> %% not yet 500 mnesia:write(User); true -> %% value has reached 500 %% get all timestamps and get the %% oldest record and delete it %% OldRecord = get_oldest_stamp(AllHere), ok = mnesia:delete_object(Record), mnesia:write(User) end end. get_oldest_stamp(UserRecords)-> %% here you do your sorting %% and return the record with %% oldest timestamp .... OldRecord.
交易中的length/1
函數不是最優的。讓我們想一個更好的方法。另外,我不知道你的時間戳是怎麼樣的,所以我們確信你有一種排序方式,找出最新的時間戳,挑出擁有這個時間戳記的記錄,然後返回它。我已經給出了這個解決方案,以適應您的設計。我也認爲我們需要一些indexing
。下一個實施對我來說似乎更好。一些如何改變記錄定義,我們引入一個字段oldest
,它需要一個bool()
,我們將它索引爲
-record(user,{ username, field1, field2, timestamp, oldest %% bool(), indexed上面的實現對我來說似乎更好。成功!
}).
insert_user(Username,Field1,Field2)-> User = #user{ username = Username, field1 = Field1, field2 = Field2, timestamp = {date(),time()}
}. insert(User).
%% execute this within a mnesia transaction
insert(#user{username = U} = User)-> case mnesia:read({user,U}) of [] -> mnesia:write(User#user{oldest = true}); AllHere -> case length(AllHere) == 500 of false -> %% unset all existing records' oldest field %% to false F = fun(UserX)-> ok = mnesia:delete_object(UserX), ok = mnesia:write(UserX#user{oldest = false}) end, [F(XX) || XX <- AllHere], ok = mnesia:write(User#user{oldest = true}); true -> [OldestRec] = mnesia:index_read(user,true,oldest), ok = mnesia:delete_object(OldestRec), ok = mnesia:write(User#user{oldest = true}) end end.
另一種方式可能是有你的記錄是
{username, value_list, timestamp}
其中VALUE_LIST包含的值的列表。你的桌子現在可以是一套而不是一個袋子,你可以做這種類型的東西
{NewList,_ignore}=lists:Split(500, [{NewFld1,NewFld2}|Value_list]),
%mnesia:write(Rec#{value_list=NewList}) type of code goes next
只要你插入。 NewList將包含至多500個元素,並且由於最老的元素在最後,所以如果您有501個元素,最後一個將放在_ignore列表中,您將...忽略。
您交易恆定時間查找您的密鑰的一些列表操作,但可能是一個很好的權衡取決於您的應用程序。您也可能能夠擺脫時間戳字段和相關代碼來維護該字段。
這種方法非常簡單(我實際上在生產中有類似的東西),但是如果記錄數量的限制很高,那麼效率可能非常低,因爲Mnesia必須讀取或寫入用戶的所有數據,每個在該用戶上執行的操作。 – igorrs