在Erlang Mnesia进行分页搜索

时间:2015-04-12 10:41:15

标签: search pagination erlang mnesia

例如,给定记录

-record(item, {
  id,
  time,
  status}).

我想搜索按时间和status =:= <<"finished">>

排序的1000到1100项

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

这取决于您的查询的样子。如果您需要按很多不同的列进行排序,那么我会考虑使用SQL而不是Mnesia。

但是如果你只需要你所描述的那种查询,你应该能够使用ordered_set类型的表来处理排序,mnesia:select/4来处理分页和约束。

这是一些未经测试的代码,为您提供要点:

% time goes first because it's our primary sort key
-record(statuses, {time, id, status}).
...
create_table() ->
  mnesia:create_table(statuses, [
                        {attributes, record_info(fields, statuses)}
                       ,{type, ordered_set}
                       ]).

-spec fetch_paged(integer()) -> {[tuple()], continuation()}|'$end_of_table'.
fetch_paged(PageSize) ->
  MatchSpec = {#statuses{id = '$1', status = <<"finished">>, _ = '_'}, [], ['$1']},
  mnesia:select(statuses, [MatchSpec], PageSize, read).

-spec next_page(continuation()) -> {[tuple()], continuation()}|'$end_of_table'.
next_page(Cont) ->
  mnesia:select(Cont).

基本上,mnesia:select/4为您提供了一页结果,并为下一页结果提供了延续。没有内置的方法可以像在SQL DB中那样跳转到第1000个结果,所以如果你需要这个能力,你可以自己构建它(保持一个时间索引,这样你就可以快速查找表中的第1000个结果是{{2015,4,12},{23,53,8}},然后在运行select时将其用作警卫。

答案 1 :(得分:0)

我认为,您应该使用mnesia:select/2选择status =:= <<"finished">>的对象,然后您可以使用lists:sorttime对结果进行排序,最后您可以使用lists:sublist/3将元素从1000减去1100

这是链接: http://www.erlang.org/doc/man/mnesia.html#select-2 http://www.erlang.org/doc/man/lists.html#sort-2 http://www.erlang.org/doc/man/lists.html#sublist-3

答案 2 :(得分:0)

你可能会使用QLC Cursor,如下所示:

order(table_name,[id,Direction]) ->
case Direction of
    descent -> fun(A,B) -> A#table_name.id > B#table_name.id end;
    ascent -> fun(A,B) -> A#table_name.id < B#table_name.id end
end;

select(universal,[Data_module,Table,Minor,Major,Order_by,Direction,Query]) ->
try
    if
        Minor == Major -> {error};
        Minor == 0; Major == 0 -> {error};
        true ->
            case apply(Data_module,order,[Table,[Order_by,Direction]]) of
                error -> {error};
                Order ->
                    Transaction = fun() ->
                        Query = qlc:q([X||X <- mnesia:table(Table)]),
                        Handler = qlc:sort(Query,[{order,Order}]),
                        Cursor = qlc:cursor(Handler),
                        if
                            Minor == 1 ->
                                Result = qlc:next_answers(Cursor,Major),
                                qlc:delete_cursor(Cursor),
                                Result;
                            true ->
                                qlc:next_answers(Cursor,Minor-1),
                                Result = qlc:next_answers(Cursor,Major-Minor+1),
                                qlc:delete_cursor(Cursor),
                                Result
                        end
                    end,
                    mnesia:transaction(Transaction)
            end
    end
catch
    Exception:Reason -> {error}
end.

QLC手册在Qlc:reference 但这种方式并不是生产中最快的方式,因为中等重负载(每秒测试10000次连接),但更多的是你会在内存可用空间内出现问题,你需要提升它