我使用mnesia为用户存储数据,记录是一个像
这样的包{username,field1,filed2,timestamp}
为了不让数据库爆炸,我想设置属于某个用户的记录数限制,比如说,如果用户的记录数达到500,那么具有最旧时间戳的记录是在插入新记录之前删除。
有一种有效的方法吗?
提前致谢。
答案 0 :(得分:0)
我提供了两种可能性。一个适合您的设计,一个引入您的记录定义的小变化。看看哪一个最适合您的需求。下面的第一个是在你的设计中工作。
-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.
答案 1 :(得分:0)
另一种方法可能是让你的记录
{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列表中,您将...忽略。
您在密钥上进行常规时间查询以进行某些列表操作,但根据您的应用程序可能是一个很好的权衡。您也可以摆脱时间戳字段和相关代码来维护该字段。