7

我有一个 mnesia 表,其中包含 f1、f2、f3 字段。现在,如果我要选择字段值为 V1 的所有行,我将使用mnesia:select并匹配规范或简单的mnesia:match_object. 现在我需要选择所有具有 V1、V2、V3 ... 或 Vn(任意长度的列表)的行作为字段 f1 的值。在 SQL 中,我会做类似的事情

SELECT * FROM tablename WHERE f3 IN (V1, V2, V3, ... , Vn)

我如何在记忆中做到这一点?

4

3 回答 3

6

对于这个问题的匹配规范解决方案,如果 QLC 被测量为不够有效。

> ets:fun2ms(fun ({_,X}=E) when X == a -> E end).
[{{'_','$1'},[{'==','$1',a}],['$_']}]

ets:fun2ms 是一个解析转换,可以将一些乐趣转换为匹配规范值。我用它作为获得我想要的 matchspec 的快速方法。我们得到一个带有 matchspec 的列表,它找到第二个元素是 a 的元组。我们可以对其他键重复它。

因此,让我们用一些东西来填充一个 ets 表来尝试一下,然后创建一个 matchspec,它只匹配第二个元素为“a”或“c”的项目。(我输入这个

ets:new(foo, [named_table]).

ets:insert(foo, [{1,a},{2,b},{3,c},{4,d}]).

Vs = [a,c].

MS = [{{'_','$1'},[{'==','$1',V}],['$_']} || V <- Vs].

ets:select(foo, MS).

当我运行它时,我得到:

[{1,a},{3,c}]
于 2010-05-26T19:21:02.490 回答
4

克里斯蒂安指出了很好的解决方案,但它可以变得更简单一些

2> ets:fun2ms(fun ({_,a}=E) -> E end).             
[{{'_',a},[],['$_']}]

所以对于你匹配你可以制作更简单的匹配规范

4> ets:new(foo, [named_table]).
foo
5> ets:insert(foo, [{1,a},{2,b},{3,c},{4,d}]).
true
6> Vs = [a,c].
[a,c]
7> MS = [{{'_',V},[],['$_']} || V <- Vs].                
[{{'_',a},[],['$_']},{{'_',c},[],['$_']}]
8> ets:select(foo, MS).
[{1,a},{3,c}]
于 2010-06-01T16:24:17.787 回答
2

如果您需要“复杂”查询,那么 QLC 是一种简洁的表述方式。QLC 是一种解析转换,它允许您在各种表(包括 mnesia 表)上使用列表理解语法。

必须具有以下包含,因为它启用了使 QLC 在此源文件中成为可能的解析转换。

-include_lib("stdlib/include/qlc.hrl").

基本查询表单如下所示,创建查询句柄,然后评估查询。

QH = qlc:q([X || X <- Xs]),
qlc:eval(QH).

然后,您可以使用http://www.erlang.org/doc/man/mnesia.html#table-1在 mnesia 表中获取后端的 QLC 表。因此,您的查询可以实现如下:

Vs = [V1,V2,...Vn],
QH = qlc:q([X || X <- mnesia:table(tablename), 
                 lists:member(X#tablename.f3, Vs)]),
qlc:eval(QH).

这需要进行表扫描,但效率不高。如果您在 f3 列上有一个索引,那么您可以转而先查询 f3 = V1,然后是 V2 等的条目,然后合并结果。

附言

另一种方法是从 V 值列表中创建一个非常复杂的匹配规范并运行 mnesia:select。

于 2010-05-26T11:32:49.343 回答