1 |
|
%% Produces filters based on lookup params |
2 |
|
-module(mam_filter). |
3 |
|
-export([produce_filter/2]). |
4 |
|
-include("mongoose_mam.hrl"). |
5 |
|
|
6 |
|
-type column() :: atom(). |
7 |
|
|
8 |
|
-type filter_field() :: {like, column(), binary()} |
9 |
|
| {le, column(), integer()} |
10 |
|
| {ge, column(), integer()} |
11 |
|
| {equal, column(), integer() | binary()} |
12 |
|
| {less, column(), integer()} |
13 |
|
| {greater, column(), integer()}. |
14 |
|
|
15 |
|
-type filter() :: [filter_field()]. |
16 |
|
-type fields() :: [#lookup_field{}]. |
17 |
|
-type params() :: map(). |
18 |
|
|
19 |
|
-export_type([filter_field/0]). |
20 |
|
-export_type([filter/0]). |
21 |
|
|
22 |
|
-define(SEARCH_WORDS_LIMIT, 10). |
23 |
|
|
24 |
|
-spec produce_filter(params(), fields()) -> list(filter_field()). |
25 |
|
produce_filter(Params, Fields) -> |
26 |
1576 |
[new_filter(Field, Value) |
27 |
1576 |
|| Field <- Fields, |
28 |
11612 |
Value <- field_to_values(Field, Params)]. |
29 |
|
|
30 |
|
field_to_values(#lookup_field{param = Param, value_maker = ValueMaker, required = Required} = Field, Params) -> |
31 |
11612 |
case maps:find(Param, Params) of |
32 |
|
{ok, Value} when Value =/= undefined -> |
33 |
2055 |
make_value(ValueMaker, Value); |
34 |
|
Other when Required -> |
35 |
:-( |
error(#{reason => missing_required_field, field => Field, params => Params, result => Other}); |
36 |
|
_ -> |
37 |
9557 |
[] |
38 |
|
end. |
39 |
|
|
40 |
42 |
make_value(search_words, Value) -> search_words(Value); |
41 |
2013 |
make_value(undefined, Value) -> [Value]. %% Default value_maker |
42 |
|
|
43 |
|
new_filter(#lookup_field{op = Op, column = Column}, Value) -> |
44 |
2083 |
{Op, Column, Value}. |
45 |
|
|
46 |
|
%% Constructs a separate LIKE filter for each word. |
47 |
|
%% SearchText example is "word1%word2%word3". |
48 |
|
%% Order of words does not matter (they can go in any order). |
49 |
|
-spec search_words(binary()) -> list(binary()). |
50 |
|
search_words(SearchText) -> |
51 |
42 |
Words = binary:split(SearchText, <<"%">>, [global]), |
52 |
42 |
[<<"%", Word/binary, "%">> || Word <- lists:sublist(Words, ?SEARCH_WORDS_LIMIT)]. |