7

f1、f2、f3などのフィールドを持つmnesiaテーブルがあります。ここで、フィールド値が V1 のすべての行を選択する場合は、mnesia:select仕様または単純な を使用して一致させmnesia:match_objectます。ここで、フィールド f1 の値として V1、V2、V3 ... または Vn (任意の長さのリスト) を持つすべての行を選択する必要があります。SQLでは、次のようなことをします

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

mnesiaでこれを行うにはどうすればよいですか?

4

3 に答える 3

6

QLC が十分に効率的ではないと測定された場合、この問題に対する一致仕様の解決策について説明します。

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

ets:fun2ms は、一部のfun を matchspec 値に変換できる解析変換です。必要な matchspec をすばやく取得する方法として使用します。2 番目の要素が a であるタプルを見つける matchspec を持つリストを取得します。他のキーについても繰り返すことができます。

ets テーブルにこれを試してみる要素を入力してから、2 番目の要素が「a」または「c」であるアイテムのみに一致する matchspec を作成します。(私はこれを入力します

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 などのエントリをクエリして、結果をマージすることができます。

PS

別の方法は、V 値のリストから非常に複雑な match-spec を作成し、mnesia:select を実行することです。

于 2010-05-26T11:32:49.343 に答える