Skip to content

Commit

Permalink
Allow to use $or with a mango JSON index
Browse files Browse the repository at this point in the history
Since apache#816, mango JSON index on compound fields can be selected only if
the selector make sure that all the fields listed in the index are
always present. This commit add a special case where all clauses of an
`$or` can ensure that a field is present.

For instance, if I had an index:

[A, B]

is_usable would now return true for the selector:

{
  "A": "foo",
  "$or": {
    "B": "bar",
    "B": "baz"
  }
}
  • Loading branch information
nono committed Nov 20, 2017
1 parent 44cca52 commit 013d2b0
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions src/mango/src/mango_selector.erl
Original file line number Diff line number Diff line change
Expand Up @@ -596,10 +596,20 @@ has_required_fields(Selector, RequiredFields) when not is_list(Selector) ->
% We can "see" through $and operator. We ignore other
% combination operators because they can't be used to restrict
% an index.
has_required_fields([{[{<<"$and">>, Args}]}], RequiredFields)
has_required_fields([{[{<<"$and">>, Args}]}], RequiredFields)
when is_list(Args) ->
has_required_fields(Args, RequiredFields);

% We can "see" through $or operator if all the clauses require
% the same field.
has_required_fields([{[{<<"$or">>, Args}]} | Rest], [Field | RequiredFields])
when is_list(Args) ->
Pred = fun(A) -> has_required_fields(A, [Field]) end,
case lists:all(Pred, Args) of
true -> has_required_fields(Rest, RequiredFields);
_ -> has_required_fields(Rest, [Field | RequiredFields])
end;

has_required_fields([{[{Field, Cond}]} | Rest], RequiredFields) ->
case Cond of
% $exists:false is a special case - this is the only operator
Expand Down Expand Up @@ -662,7 +672,7 @@ has_required_fields_and_false_test() ->
Normalized = normalize(Selector),
?assertEqual(false, has_required_fields(Normalized, RequiredFields)).

has_required_fields_or_test() ->
has_required_fields_or_false_test() ->
RequiredFields = [<<"A">>],
Selector = {[{<<"$or">>,
[
Expand All @@ -673,4 +683,18 @@ has_required_fields_or_test() ->
Normalized = normalize(Selector),
?assertEqual(false, has_required_fields(Normalized, RequiredFields)).

-endif.
has_required_fields_or_true_test() ->
RequiredFields = [<<"A">>, <<"B">>, <<"C">>],
Selector = {[{<<"A">>, "foo"},
{<<"$or">>,
[
{[{<<"B">>, <<"bar">>}]},
{[{<<"B">>, <<"baz">>}]}
]
},
{<<"C">>, "qux"}
]},
Normalized = normalize(Selector),
?assertEqual(true, has_required_fields(Normalized, RequiredFields)).

-endif.

0 comments on commit 013d2b0

Please sign in to comment.