Skip to content

Commit

Permalink
Add mongo optimization to convert $in/$nin into $eq/$ne (for special …
Browse files Browse the repository at this point in the history
…case)

When argument to $in/$nin call is a list with **single** element convert it
to $eq/$ne. For some reason it is slow on some mongo versions.

Update tests to validate this behaviour
  • Loading branch information
asereda-gs committed Apr 24, 2020
1 parent 31de701 commit 09c002c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
Expand Up @@ -277,7 +277,10 @@ public void basic() {
check(person.fullName.is("John")
.age.is(22)).hasSize(1);
check(person.fullName.is("_MISSING_")).empty();
check(person.fullName.in(Collections.emptyList())).empty();
check(person.fullName.in(Collections.singleton("John"))).hasSize(1);
check(person.fullName.in("John", "test2")).hasSize(1);
check(person.fullName.notIn(Collections.singleton("John"))).empty();
check(person.fullName.notIn("John", "test2")).empty();

// true / false
Expand Down
Expand Up @@ -212,6 +212,31 @@ protected void optional() {
values(string.optional.is("")).isEmpty();
}

/**
* cases for {@code foo in [1]} or {@code foo not in [1]}.
* When list has just one element
*/
@Test
void inNotIn_singleElement() {
repository.insert(generator.get().withId("id1").withValue("value1"));
repository.insert(generator.get().withId("id2").withValue(""));

// for id
ids(string.id.in(Collections.emptyList())).isEmpty();
ids(string.id.in(Collections.singleton("id1"))).isOf("id1");
ids(string.id.notIn(Collections.singleton("id1"))).isOf("id2");
ids(string.id.notIn(Collections.singleton("id2"))).isOf("id1");
ids(string.id.notIn(Collections.emptyList())).hasContentInAnyOrder("id1", "id2");

// for value
ids(string.value.in(Collections.emptyList())).isEmpty();
ids(string.value.in(Collections.singleton("value1"))).isOf("id1");
ids(string.value.notIn(Collections.singleton("value1"))).isOf("id2");
ids(string.value.notIn(Collections.singleton(""))).isOf("id1");
ids(string.value.notIn(Collections.emptyList())).hasContentInAnyOrder("id1", "id2");

}

/**
* validate {@code one() / oneOrNone() / exists()} methods
*/
Expand Down
Expand Up @@ -123,6 +123,12 @@ private Bson binaryCall(Call call) {
if (op == Operators.IN || op == Operators.NOT_IN) {
final List<Object> values = Visitors.toConstant(call.arguments().get(1)).values();
Preconditions.checkNotNull(values, "not expected to be null for %s", op);
if (values.size() == 1) {
// optimization: convert IN, NIN (where argument is a list with single element) into EQ / NE
Operators newOperator = op == Operators.IN ? Operators.EQUAL : Operators.NOT_EQUAL;
Call newCall = Expressions.call(newOperator, call.arguments().get(0), Expressions.constant(values.get(0)));
return binaryCall(newCall);
}
return op == Operators.IN ? Filters.in(field, values) : Filters.nin(field, values);
}

Expand Down

0 comments on commit 09c002c

Please sign in to comment.