2011-11-10 2 views
4

私は、ユーザーのデータを格納するためにmnesiaを使用して、レコードがmnesiaの特定のキーの下にあるレコードの数を制限する慣習的な方法は何ですか?

{ユーザー名、フィールド1、filed2、タイムスタンプ}

データベースが爆発させないためにはのような構造の袋で、私は設定したいです例えば、あるユーザのレコード数が500に達した場合、新しいレコードが挿入される前に最も古いタイムスタンプのレコードが削除されます。

効率的な方法はありますか?

ありがとうございます。

答えて

0

私は2つの可能性を提供しました。デザイン内に収まるものと、レコード定義に小さな変化をもたらすもの。あなたのニーズに最も適したものを見てください。下の最初のものがあなたのデザインの中で働いています。

 
-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.
上記の実装は私にとっては良いようです。成功 !!

0

もう一つの方法は、あなたのレコードがVALUE_LISTは、値のリストが含まれ

{username, value_list, timestamp} 

も持っているかもしれません。あなたのテーブルはバッグの代わりにセットになることができ、このタイプのものを行うことができます

{NewList,_ignore}=lists:Split(500, [{NewFld1,NewFld2}|Value_list]), 
%mnesia:write(Rec#{value_list=NewList}) type of code goes next 

いつでも挿入することができます。 NewListには最大500個の要素が含まれ、最も古い要素が最後にあるため、501個の要素がある場合、最後の要素は_ignoreリストになります。無視します。

あなたの取引では、一部のリスト操作のためにあなたのキーを定期的に検索しますが、あなたのアプリケーションによっては良いトレードオフかもしれません。また、タイムスタンプフィールドと関連コードを取り除いて、そのフィールドを維持することもできます。

+0

このアプローチは非常に簡単です(私は実際には製造上の類似点を持っています)。しかし、Mnesiaはユーザーのすべてのデータを読み書きする必要があるため、レコード数の上限が高いと非常に非効率ですそのユーザーに対して実行されたすべての操作。 – igorrs

関連する問題