Erlang Mnesia Select 结果与 read、foldl 不同
Erlang Mnesia Select result not same as read, foldl
我有 3 个用例 return 从失忆症 table 收集数据
1. return a table 的所有值所以我使用 foldl,
2. return 1 行所以我使用 read
3. return 基于条件的可变数量的记录,所以我使用 select。
我想使用相同的代码来管理结果,但是 select return 的数据结构不同。我希望有人可以帮助我将我的 select 重组为 return,就像其他人一样。
下面是问题的示例代码和结果。问题是 select 不像 read 和 foldl 那样 return table 的记录名称。
-module(testselect2).
-export([runtest/0]).
-record(record_a, {b, c, d}).
-record(record_b, {record_a, e}).
-record(record_c, {record_b, f, intval}).
runtest() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(record_c, [{attributes, record_info(fields, record_c)}]),
A1 = #record_a{b = "R1", c = "T1", d = "C1"},
B1 = #record_b{record_a = A1, e = "E1"},
C1 = #record_c{record_b = B1, f = "F1", intval = 100},
A2 = #record_a{b = "R2", c = "T2", d = "C2"},
B2 = #record_b{record_a = A2, e = "E2"},
C2 = #record_c{record_b = B2, f = "F2", intval = 200},
A3 = #record_a{b = "R3", c = "T3", d = "C3"},
B3 = #record_b{record_a = A3, e = "E3"},
C3 = #record_c{record_b = B3, f = "F3", intval = 300},
{atomic, Rw} = mnesia:transaction(
fun () ->
mnesia:write(C1),
mnesia:write(C2),
mnesia:write(C3)
end),
io:fwrite("Result write = ~w~n", [Rw]),
{atomic, Rr} = mnesia:transaction(
fun () ->
mnesia:read({record_c, B1})
end),
io:fwrite("Result read = ~w~n", [Rr]),
{atomic, Rf} =
mnesia:transaction(fun () ->
mnesia:foldl(fun (Rec, Acc) -> [Rec | Acc] end,
[],
record_c)
end),
io:fwrite("Result foldl = ~w~n", [Rf]),
MatchHead = #record_c{record_b='', f='', intval=''},
Guard = {'>', '', 100},
Result = {{'', '', ''}},
{atomic, Rs} = mnesia:transaction(
fun () ->
mnesia:select(record_c, [{MatchHead, [Guard], [Result]}])
end),
io:fwrite("Result select = ~w~n", [Rs]).
=====
结果
44> testselect2:runtest().
结果写入 = ok
读取结果 = [{record_c,{record_b,{record_a,[82,49],[84,49],[67,49]},[ 69,49]},[70,49],100}]
结果 foldl = [{record_c,{record_b,{record_a,[82,49],[84,49],[67,49]},[ 69,49]},[70,49],100},{record_c,{record_b,{record_a,[82,51],[84,51],[67 ,51]},[69,51]},[70,51],300},{record_c,{record_b,{record_a,[82,50],[84 ,50],[67,50]},[69,50]},[70,50],200}]
结果select = [{{record_b,{record_a,[82,51],[84,51],[67,51]},[69, 51]},[70,51],300},{{record_b,{record_a,[82,50],[84,50],[67,50]},[69, 50]},[70,50],200}]
还行
如您所见,上面的 read 和 foldl 记录以 {record_c,{... 开头,其中 select 缺少 record_c,只有 {{...
我一直无法找到使 select 到 return 相同结构的方法,因此我的处理代码可以适用于所有 3 个用例。任何建议将不胜感激。
我不是记忆专家,但我知道当你使用 ETS 匹配表达式时,你决定了结果是什么样子。您使用 Result = {{'', '', ''}}
来创建结果项,这使得它们在一个元组中以三元组的形式出现,正如我们在您的输出中看到的那样。根据 ets:select/1
,您想使用特殊变量 '$_'
来 return 整个匹配对象,因此这应该可以代替您的 Result = ...
行:
Result = '$_',
我有 3 个用例 return 从失忆症 table 收集数据 1. return a table 的所有值所以我使用 foldl, 2. return 1 行所以我使用 read 3. return 基于条件的可变数量的记录,所以我使用 select。
我想使用相同的代码来管理结果,但是 select return 的数据结构不同。我希望有人可以帮助我将我的 select 重组为 return,就像其他人一样。
下面是问题的示例代码和结果。问题是 select 不像 read 和 foldl 那样 return table 的记录名称。
-module(testselect2).
-export([runtest/0]).
-record(record_a, {b, c, d}).
-record(record_b, {record_a, e}).
-record(record_c, {record_b, f, intval}).
runtest() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(record_c, [{attributes, record_info(fields, record_c)}]),
A1 = #record_a{b = "R1", c = "T1", d = "C1"},
B1 = #record_b{record_a = A1, e = "E1"},
C1 = #record_c{record_b = B1, f = "F1", intval = 100},
A2 = #record_a{b = "R2", c = "T2", d = "C2"},
B2 = #record_b{record_a = A2, e = "E2"},
C2 = #record_c{record_b = B2, f = "F2", intval = 200},
A3 = #record_a{b = "R3", c = "T3", d = "C3"},
B3 = #record_b{record_a = A3, e = "E3"},
C3 = #record_c{record_b = B3, f = "F3", intval = 300},
{atomic, Rw} = mnesia:transaction(
fun () ->
mnesia:write(C1),
mnesia:write(C2),
mnesia:write(C3)
end),
io:fwrite("Result write = ~w~n", [Rw]),
{atomic, Rr} = mnesia:transaction(
fun () ->
mnesia:read({record_c, B1})
end),
io:fwrite("Result read = ~w~n", [Rr]),
{atomic, Rf} =
mnesia:transaction(fun () ->
mnesia:foldl(fun (Rec, Acc) -> [Rec | Acc] end,
[],
record_c)
end),
io:fwrite("Result foldl = ~w~n", [Rf]),
MatchHead = #record_c{record_b='', f='', intval=''},
Guard = {'>', '', 100},
Result = {{'', '', ''}},
{atomic, Rs} = mnesia:transaction(
fun () ->
mnesia:select(record_c, [{MatchHead, [Guard], [Result]}])
end),
io:fwrite("Result select = ~w~n", [Rs]).
===== 结果
44> testselect2:runtest().
结果写入 = ok
读取结果 = [{record_c,{record_b,{record_a,[82,49],[84,49],[67,49]},[ 69,49]},[70,49],100}]
结果 foldl = [{record_c,{record_b,{record_a,[82,49],[84,49],[67,49]},[ 69,49]},[70,49],100},{record_c,{record_b,{record_a,[82,51],[84,51],[67 ,51]},[69,51]},[70,51],300},{record_c,{record_b,{record_a,[82,50],[84 ,50],[67,50]},[69,50]},[70,50],200}]
结果select = [{{record_b,{record_a,[82,51],[84,51],[67,51]},[69, 51]},[70,51],300},{{record_b,{record_a,[82,50],[84,50],[67,50]},[69, 50]},[70,50],200}]
还行
如您所见,上面的 read 和 foldl 记录以 {record_c,{... 开头,其中 select 缺少 record_c,只有 {{...
我一直无法找到使 select 到 return 相同结构的方法,因此我的处理代码可以适用于所有 3 个用例。任何建议将不胜感激。
我不是记忆专家,但我知道当你使用 ETS 匹配表达式时,你决定了结果是什么样子。您使用 Result = {{'', '', ''}}
来创建结果项,这使得它们在一个元组中以三元组的形式出现,正如我们在您的输出中看到的那样。根据 ets:select/1
,您想使用特殊变量 '$_'
来 return 整个匹配对象,因此这应该可以代替您的 Result = ...
行:
Result = '$_',