It is not always easy to do complicated queries over ETS tables or mnesia.
The official syntax to make queries with select/2 is really cryptic.
Here is an example from the official Erlang docs. The query returns the name of each male person aged more then 30.
MatchHead = #person{name='$1', sex=male, age='$2', _='_'},
Guard = {'>', '$2', 30},
Result = '$1',
mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
Criterias are expressed with $ and the whole thing becomes quite convulted for anything more complicated.
Furthermore it is impossible to do what would be basic operations in other database engines, like sorting the results.
But, a module exists that makes queries better legible . QLC that stands for Query List Comprehension. It supports Mnesia, ETS and DETS.
Here is the previous query, rewritten:
Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
In this case the query is expressed as a list comprehension. Criterias are written in a comprehensible manner in the second par of the list comprehension.
If you want to execute this query in Mnesia, you have to do so in a transaction.
-include_lib("stdlib/include/qlc.hrl")
Transaction = fun() ->
Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
qlc:eval(Query)
end,
mnesia:transaction(Transaction),
To efficiently sort the result, qlc provides qlc:sort.
-include_lib("stdlib/include/qlc.hrl")
Transaction = fun() ->
Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
Order = fun(A, B) ->
B#person.age > A#person.age
end,
qlc:eval(qlc:sort(Query, [order, Order]))
end,
mnesia:transaction(Transaction),
I have not yet explored all the possibilities of QLC but the syntax it offers has convinced me to use it as often as posible. The query maintainance becomes much easier.
One last thing. It is possible to create your own modules that can be used with QLC. You can propose a search syntax that is much nicer with a backend altogether different from ETS or Mnesia.
