Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #2209 Several improvements in some edgecase querydsl scenarios #2235

Merged
merged 5 commits into from Sep 16, 2016

Conversation

@Mpdreamz
Copy link
Member

commented Sep 4, 2016

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are boolean themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to result1

bool:
  must:
     bool: should:,
     bool: should:

now we do result1 && bq3 since result1 is a must we can not merge the
should from bq3 on it and thus we need to wrap to result2

bool:
  must:
    bool:
      must:
        bool: should //bq1
        bool: should //bq2
    bool: should: //bq3

This is still semantically correct but now imagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow or in the best case query graphs that are unnecessary too deep
as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similarly the same happened if you'd || or a bunch of boolean queries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;

The & or | bitwise operators were not pure and could potentially steal clauses from
q and adding them to the new result. Causing problems when we want to
apply q again and again and again.

@Mpdreamz

This comment has been minimized.

Copy link
Member Author

commented Sep 9, 2016

Machine info

Host Process Environment Information:
BenchmarkDotNet.Core=v0.9.9.0
OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i7-4750HQ CPU 2.00GHz, ProcessorCount=8
Frequency=1948624 ticks, Resolution=513.1826 ns, Timer=TSC
CLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE
GC=Concurrent Workstation
JitModules=clrjit-v4.6.2001.0

Type=BooleanAllocationBenchmark  Mode=Throughput  LaunchCount=3  
WarmupCount=5  TargetCount=10  Type=BooleanAllocationBenchmark  
Mode=Throughput  LaunchCount=3  WarmupCount=5  
TargetCount=10  

Comparing &=:

var c = new QueryContainer();
QueryContainer q =new TermQuery { Field = "x", Value = "x" }; 
for (var i=0;i<1000;i++)
    c &= q;

Latest released version (2.4.5)

Median StdDev Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
2.8882 ms 0.4175 ms 3,516.00 83.00 - 3.308.101,43

This branch:

Median StdDev Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
1.6182 ms 0.3165 ms 1,681.00 49.00 - 1.684.119,54

Comparing |=:

var c = new QueryContainer();
QueryContainer q =new TermQuery { Field = "x", Value = "x" }; 
for (var i=0;i<1000;i++)
    c |= q;

Latest released version (2.4.5)

Median StdDev Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
2.4455 ms 0.4268 ms 3,482.00 83.00 - 3.824.267,35

This branch:

Median StdDev Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
1.6811 ms 0.1959 ms 1,832.00 16.00 - 1.652.231,83
@Mpdreamz

This comment has been minimized.

Copy link
Member Author

commented Sep 9, 2016

This PR also adds some documentation around performance of the bool query dsl, if you know you need a single bool with a lot of must clauses doing this:

QueryContainer q = new TermQuery { Field = "x", Value = "x" };
var x = Enumerable.Range(0, 1000).Select(f => q).ToArray();
var boolQuery = new BoolQuery
{
    Must = x
};

Is going to peform muuuuuch better which is not that crazy considering we need to reevaluate the bools merge-ability on each bitwise operation.

Median StdDev Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
31.2520 us 0.4767 us 439.00 - - 7.737,15
@Mpdreamz

This comment has been minimized.

Copy link
Member Author

commented Sep 9, 2016

This PR also fixes a small difference in behaviour in the initializer syntax between:

Our documented approach

var search = new SearchRequest 
{
    Query = new BoolQuery {}
}

And undocumented but still valid:

var search = new SearchRequest 
{
    Query = new QueryContainer(new BoolQuery {})
}

The implicit conversion was in charge of carrying some characteristics (IsStrict/IsVerbatim) from QueryBase over to QueryContainer which caused problems if you used the constructor directly.

You *can* use bitwise assignments in a loop to combine many queries into a bigger bool.

NOTE: This needs NEST 2.4.6 or higher. Prior versions did not do a good job flattening the result in the most optimal way and could cause a stackoverflow when doing ~2000 iterations In later version you can combine as many as you'd like but please keep mind of the following performance recommendations

This comment has been minimized.

Copy link
@Mpdreamz

Mpdreamz Sep 9, 2016

Author Member

This needs to be updated to specifically mention we did not do a good job combining many bools this way, other queries were flattened correctly.

@gmarz

This comment has been minimized.

Copy link
Member

commented Sep 9, 2016

LGTM 👍 Awesome work @Mpdreamz !

@russcam
Copy link
Contributor

left a comment

This is great @Mpdreamz! Much cleaner 😄

I have a few small comments, but otherwise LGTM

var list = enumerable?.ToList();
return list.HasAny() ? list : null;
var list = enumerable.AsInstanceOrToListOrNull();
return list == null || list.Count > 0 ? list : null;

This comment has been minimized.

Copy link
@russcam

russcam Sep 16, 2016

Contributor

Is this correct? I think this should only return the list if it is not null and has items?

This comment has been minimized.

Copy link
@Mpdreamz

Mpdreamz Sep 16, 2016

Author Member

👍 no

This comment has been minimized.

Copy link
@Mpdreamz

Mpdreamz Sep 16, 2016

Author Member

actually it is correct :) if list == null || list.Count > 0 = list != null && list.Count > 0 has the same effect here. Changing it to the latter for readability

@@ -0,0 +1,188 @@
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/2.3

This comment has been minimized.

Copy link
@russcam

russcam Sep 16, 2016

Contributor

Do we want to include this file in our documentation?

@@ -0,0 +1,198 @@
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/2.3

This comment has been minimized.

Copy link
@russcam

russcam Sep 16, 2016

Contributor

Do we want to include this file in our documentation?

@@ -0,0 +1,160 @@
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/2.3

This comment has been minimized.

Copy link
@russcam

russcam Sep 16, 2016

Contributor

Do we want to include this file in our documentation?

Mpdreamz added some commits Sep 4, 2016

This commit brings about several improvements in some edgecase querydsl
scenarios

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are booleans themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to `result1`

bool:
  must:
     bool: should:,
     bool: should:

now we do `result1 && bq2` since result1 is a must we can not merge the
should from `bq2` on it and thus we need to wrap to `result2`

bool:
  should:
    bool:
      must:
        bool: should:,
	bool: should:
    bool: should: //bq2

This is still sementically correct but now immagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow and query graphs that are way too deep
unnecessary as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similary the same happened if you'd || or a bunch of booleanqueries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

```csharp
var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;
```

The & or | bitwise operators were not pure and could potentially steal clauses from
`q` and adding them to the new result. Cuasing problems when we want to
apply q again and again and again.

@Mpdreamz Mpdreamz force-pushed the fix/bitwise-ops-improvements branch from 0beb4b1 to 95ac452 Sep 16, 2016

@Mpdreamz Mpdreamz merged commit dcb56f9 into 2.x Sep 16, 2016

1 check passed

CLA Commit author has signed the CLA
Details

Mpdreamz added a commit that referenced this pull request Sep 16, 2016

fix #2209 Several improvements in some edgecase querydsl scenarios (#…
…2235)

* This commit brings about several improvements in some edgecase querydsl
scenarios

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are booleans themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to `result1`

bool:
  must:
     bool: should:,
     bool: should:

now we do `result1 && bq2` since result1 is a must we can not merge the
should from `bq2` on it and thus we need to wrap to `result2`

bool:
  should:
    bool:
      must:
        bool: should:,
	bool: should:
    bool: should: //bq2

This is still sementically correct but now immagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow and query graphs that are way too deep
unnecessary as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similary the same happened if you'd || or a bunch of booleanqueries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

```csharp
var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;
```

The & or | bitwise operators were not pure and could potentially steal clauses from
`q` and adding them to the new result. Cuasing problems when we want to
apply q again and again and again.

* attempt to minimize allocations in the bool dsl by reusing lists and already instantiated bool queries

* documentation commit, hacked around asciidotnet not supporting tables just yet :) russcam/asciidotnet#2

* updated bool dsl performance section in the documentation

* inverted if statement for readabillity and removed some of the tests in the documentation output

Conflicts:
	docs/client-concepts/low-level/connecting.asciidoc
	src/Nest/Nest.csproj
	src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs
	src/Nest/QueryDsl/Visitor/DslPrettyPrintVisitor.cs
	src/Tests/Framework/SerializationTests/SerializationTestBase.cs
	src/Tests/QueryDsl/QueryDslUsageTestsBase.cs
	src/Tests/Tests.csproj

Mpdreamz added a commit that referenced this pull request Sep 16, 2016

fix #2209 Several improvements in some edgecase querydsl scenarios (#…
…2235)

* This commit brings about several improvements in some edgecase querydsl
scenarios

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are booleans themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to `result1`

bool:
  must:
     bool: should:,
     bool: should:

now we do `result1 && bq2` since result1 is a must we can not merge the
should from `bq2` on it and thus we need to wrap to `result2`

bool:
  should:
    bool:
      must:
        bool: should:,
	bool: should:
    bool: should: //bq2

This is still sementically correct but now immagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow and query graphs that are way too deep
unnecessary as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similary the same happened if you'd || or a bunch of booleanqueries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

```csharp
var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;
```

The & or | bitwise operators were not pure and could potentially steal clauses from
`q` and adding them to the new result. Cuasing problems when we want to
apply q again and again and again.

* attempt to minimize allocations in the bool dsl by reusing lists and already instantiated bool queries

* documentation commit, hacked around asciidotnet not supporting tables just yet :) russcam/asciidotnet#2

* updated bool dsl performance section in the documentation

* inverted if statement for readabillity and removed some of the tests in the documentation output

Conflicts:
	docs/client-concepts/low-level/connecting.asciidoc
	src/Nest/Nest.csproj
	src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs
	src/Nest/QueryDsl/Visitor/DslPrettyPrintVisitor.cs
	src/Tests/Framework/SerializationTests/SerializationTestBase.cs
	src/Tests/QueryDsl/QueryDslUsageTestsBase.cs
	src/Tests/Tests.csproj

Mpdreamz added a commit that referenced this pull request Sep 16, 2016

fix #2209 Several improvements in some edgecase querydsl scenarios (#… (
#2266)

* fix #2209 Several improvements in some edgecase querydsl scenarios (#2235)

* This commit brings about several improvements in some edgecase querydsl
scenarios

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are booleans themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to `result1`

bool:
  must:
     bool: should:,
     bool: should:

now we do `result1 && bq2` since result1 is a must we can not merge the
should from `bq2` on it and thus we need to wrap to `result2`

bool:
  should:
    bool:
      must:
        bool: should:,
	bool: should:
    bool: should: //bq2

This is still sementically correct but now immagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow and query graphs that are way too deep
unnecessary as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similary the same happened if you'd || or a bunch of booleanqueries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

```csharp
var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;
```

The & or | bitwise operators were not pure and could potentially steal clauses from
`q` and adding them to the new result. Cuasing problems when we want to
apply q again and again and again.

* attempt to minimize allocations in the bool dsl by reusing lists and already instantiated bool queries

* documentation commit, hacked around asciidotnet not supporting tables just yet :) russcam/asciidotnet#2

* updated bool dsl performance section in the documentation

* inverted if statement for readabillity and removed some of the tests in the documentation output

Conflicts:
	docs/client-concepts/low-level/connecting.asciidoc
	src/Nest/Nest.csproj
	src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs
	src/Nest/QueryDsl/Visitor/DslPrettyPrintVisitor.cs
	src/Tests/Framework/SerializationTests/SerializationTestBase.cs
	src/Tests/QueryDsl/QueryDslUsageTestsBase.cs
	src/Tests/Tests.csproj

* documentation update

Mpdreamz added a commit that referenced this pull request Sep 16, 2016

fix #2209 Several improvements in some edgecase querydsl scenarios (#… (
#2265)

* fix #2209 Several improvements in some edgecase querydsl scenarios (#2235)

* This commit brings about several improvements in some edgecase querydsl
scenarios

We always flattened situations like:

query1 && query2 && query3 into a single bool query with 3 must clauses.

But if the queries are booleans themselves that can't be merged we would
generate deeply nested pairs of two.

For instance we have 3 bool queries with only should clauses

bq1 && bq2 && bq3

ideally we'd generate:

bool:
  must:
     bool: should:,
     bool: should:,
     bool: should:

However due to the bitwise binary nature the way they were combined was:

Step1:

bq1 && b2 - both sides only have should clauses merging them would be
wrong so we wrap to `result1`

bool:
  must:
     bool: should:,
     bool: should:

now we do `result1 && bq2` since result1 is a must we can not merge the
should from `bq2` on it and thus we need to wrap to `result2`

bool:
  should:
    bool:
      must:
        bool: should:,
	bool: should:
    bool: should: //bq2

This is still sementically correct but now immagine you are doing this
in a loop combining thousands of these. Admittingly an edgecase it would
cause a nasty stackoverflow and query graphs that are way too deep
unnecessary as is showcased by #2209

This is now fixed in a way that does not need constant traversal of to
see if a bool must or should clause consists of only bools.

Similary the same happened if you'd || or a bunch of booleanqueries only
containing musts.

A third fix is that we no longer modify the original query when stealing
clauses. This could cause nasty errors when reusing a static bool query
e.g

```csharp
var q = Query<Project>.Bool(b => b.Should(ATermQuery).Must(ATermQuery));
var c = new QueryContainer();
for(int i = 0;i<1000;i++) c &= q;
```

The & or | bitwise operators were not pure and could potentially steal clauses from
`q` and adding them to the new result. Cuasing problems when we want to
apply q again and again and again.

* attempt to minimize allocations in the bool dsl by reusing lists and already instantiated bool queries

* documentation commit, hacked around asciidotnet not supporting tables just yet :) russcam/asciidotnet#2

* updated bool dsl performance section in the documentation

* inverted if statement for readabillity and removed some of the tests in the documentation output

Conflicts:
	docs/client-concepts/low-level/connecting.asciidoc
	src/Nest/Nest.csproj
	src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs
	src/Nest/QueryDsl/Visitor/DslPrettyPrintVisitor.cs
	src/Tests/Framework/SerializationTests/SerializationTestBase.cs
	src/Tests/QueryDsl/QueryDslUsageTestsBase.cs
	src/Tests/Tests.csproj

* documentation update

* documentation update

@Mpdreamz Mpdreamz deleted the fix/bitwise-ops-improvements branch Sep 16, 2016

Mpdreamz added a commit that referenced this pull request Dec 7, 2016

fix #2461 &= in the bool DSL is viral.
The performance and allocations fixes in #2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from #2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.

russcam added a commit that referenced this pull request Dec 9, 2016

fix #2461 &= in the bool DSL is viral.
The performance and allocations fixes in #2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from #2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.

russcam added a commit that referenced this pull request Dec 9, 2016

fix #2461 &= in the bool DSL is viral.
The performance and allocations fixes in #2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from #2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.

(cherry picked from commit 10ee84a)

russcam added a commit that referenced this pull request Dec 12, 2016

fix #2461 &= in the bool DSL is viral.
The performance and allocations fixes in #2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from #2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.

(cherry-picked from commit 10ee84a)

Mpdreamz added a commit that referenced this pull request Dec 16, 2016

fix #2461 &= in the bool DSL is viral. (#2487)
The performance and allocations fixes in #2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from #2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.

(cherry-picked from commit 10ee84a)

awelburn added a commit to Artesian/elasticsearch-net that referenced this pull request Nov 6, 2017

fix elastic#2461 &= in the bool DSL is viral.
The performance and allocations fixes in elastic#2235 also introduced virality
on the QueryContainer when using &= assignment. The composed result was
correct but the QueryContainer composed of `&=` would be left marked as
`CreatedByTheBoolDsl` which meant it was marked for reuse.

If you then later combined it with && (andAssignedQuery && newQuery) the resulting
query would be correct but if you rely on `andAssignedQuery` not being
mutated you'd be in for a nasty suprise.

A QueryContainer composed with `&&` did not expose the same virality
problems.

Removed the notion of trying to reuse all together since the big
performance gain from elastic#2235 is that we can flatten many boolean should
queries using `&=` or `&&` or visa versa many boolean must queries with
`|=` or `||`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.