【问题标题】:Erlang Mnesia Unique keys except primariy keyErlang Mnesia 唯一键,除了主键
【发布时间】:2013-08-03 20:25:56
【问题描述】:

我想在mnesia中创建下表:

-record(cuser, {
id,
login_id,
email,
....}).

login_id 和 email 在业务逻辑中都是唯一的。

如何在 mnesia 中实现它?

提前致谢。

【问题讨论】:

    标签: erlang unique-key mnesia


    【解决方案1】:

    最简单的方法是在单个 mnesia 事务中执行所有测试。下面的代码就可以了。

    请注意,此代码不会检查 Id 是否已经存在,因此如果您尝试使用现有 id 和新登录 id 和电子邮件添加新用户,它将简单地覆盖现有记录(即 set 的行为)。

    %% record declaration
    -record (cuser, {id,login_id,email}),
    %% create a table for test
    mnesia:create_schema([node()]),
    application:start(mnesia),
    mnesia:create_table(cuser,[{attributes,record_info(fields,cuser)},
                               {index,[#cuser.login_id,#cuser.email]},
                               {disc_copies,[node()]},
                               {type,set}]),
    %% write 2 record for test
    Wr = fun(I,L,E) -> mnesia:write(#cuser{id=I,login_id=L,email=E}) end,
    mnesia:transaction(Wr,[u1,l1,m1]),
    mnesia:transaction(Wr,[u2,l2,m2]),
    %% create a function for filtering
    M = fun(Nl,Ne) -> 
            Match = ets:fun2ms(fun(#cuser{id=I,login_id=Li,email=E}) when Li =:= Nl; E =:= Ne -> {I,Li,E} end),
            mnesia:select(cuser,Match)
        end,
    %% create a function to add a new user
    Add = fun(I,Nl,Ne) ->
            {atomic,R} = mnesia:transaction(M,[Nl,Ne]),
            case R of
              [] -> mnesia:transaction(Wr,[I,Nl,Ne]);
              R -> {already_exist,R}
            end
           end,
    %% add new user
    mnesia:transaction(Add,[i3,l3,m1]), %% will return {atomic,{already_exist,[{u1,l1,m1}]}}
    mnesia:transaction(Add,[i3,l3,m3]), %% will return {atomic,{atomic,ok}}
    

    要检查 Id 是否已经存在,只需在过滤器函数中添加测试:

    %% create a function for filtering
    M = fun(Ni,Nl,Ne) -> 
            Match = ets:fun2ms(fun(#cuser{id=I,login_id=Li,email=E}) when I =:= Ni; Li =:= Nl; E =:= Ne -> {I,Li,E} end),
            mnesia:select(cuser,Match)
        end,
    %% create a function to add a new user
    Add = fun(I,Nl,Ne) ->
            {atomic,R} = mnesia:transaction(M,[I,Nl,Ne]),
            case R of
              [] -> mnesia:transaction(Wr,[I,Nl,Ne]);
              R -> {already_exist,R}
            end
           end,
    

    【讨论】:

    • 感谢您的回复。我有一个关于同步的问题。如果两个客户端同时提交“添加用户”请求。一个是[i4, l4, m4],一个是[i5, l5, m4],结果是什么?
    • 你不知道哪一个会赢,但应该只记录一个用户,另一个用户会已经_exist。
    • 是的,这就是返回值的意思:{atomic,Something}。
    • 避免在 mnesia 中嵌套事务,因为这可能非常昂贵,即 Add = fun() 不应该调用 mnesia:transaction/2 而是直接调用 'M' 和 'Wr'
    【解决方案2】:

    Mneisa 是一个key-value存储系统,只保证key的唯一性。

    我能想到的唯一方法是使用 tuple{id, login_id} 保存为主键。

    很遗憾,这只能保证其中一个是独一无二的。但是,至少您可以使用{id, login_id} 查询一个项目。

    例如:

    -record(cuser, {
        uid, %uid = {id, login_id}
        email,
        ....}).
    

    【讨论】:

      猜你喜欢
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多