Skip to content

Commit

Permalink
Handle canMatchSearchAfter for frozen context scenario
Browse files Browse the repository at this point in the history
Signed-off-by: Chaitanya Gohel <gashutos@amazon.com>
  • Loading branch information
gashutos committed Nov 17, 2023
1 parent 37ec313 commit 5236b2f
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Fix 'org.apache.hc.core5.http.ParseException: Invalid protocol version' under JDK 16+ ([#4827](https://github.com/opensearch-project/OpenSearch/pull/4827))
- Fix compression support for h2c protocol ([#4944](https://github.com/opensearch-project/OpenSearch/pull/4944))
- Don't over-allocate in HeapBufferedAsyncEntityConsumer in order to consume the response ([#9993](https://github.com/opensearch-project/OpenSearch/pull/9993))
- Handle canMatchSearchAfter for frozen context scenario ([#11249](https://github.com/opensearch-project/OpenSearch/pull/11249))

### Security

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,99 @@ setup:
- match: { aggregations.date.buckets.1.key: 1540857600000 }
- match: { aggregations.date.buckets.1.key_as_string: "2018-10-30T00:00:00.000Z" }
- match: { aggregations.date.buckets.1.doc_count: 2 }


---
"date with nested sort now":
- skip:
version: " - 2.12.99"
reason: fixed in 3.0.0

# This tests cover scenario where nested sort have now() in date field type.
# For this test, we have date field as nested field and we trigger asc/desc sort
# on that nested field. `filter` clause is needed when we sort any nested field,
# like in this case, "gte": "now/h" says sort nested field date_field only where
# document is having value greater than current time now().
# Nested field sort query doesn't sort documents if it is not qualified through
# `filter` clause.
# Only adding tests for `gte` as `lte` would be same behaviour

- do:
indices.create:
index: test
body:
mappings:
properties:
nested_field:
type: nested
properties:
date_field:
type: date
format: date_optional_time
- do:
bulk:
refresh: true
index: test
body: |
{"index":{}}
{"nested_field": [{"date_field": "3023-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "3024-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "3025-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "3026-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "3027-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "2022-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "2023-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "2021-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "2020-10-26T12:00:00+09:00"}]}
{"index":{}}
{"nested_field": [{"date_field": "2019-10-26T12:00:00+09:00"}]}
# gte: now/h with the desc sort
- do:
search:
index: test
body:
size: 5
sort: [{ nested_field.date_field: { mode: max, order: desc, nested: { path: nested_field, filter: { bool: { filter : [{ range : { nested_field.date_field: { gte: now/h, time_zone: +09:00} } }] } } } } } ]
- match: {hits.total.value: 10 }
- length: {hits.hits: 5 }
- match: { hits.hits.0._index: test }
- match: { hits.hits.0._source.nested_field.0.date_field: "3027-10-26T12:00:00+09:00" }
- match: { hits.hits.0.sort: [33381428400000] }
- match: { hits.hits.1._source.nested_field.0.date_field: "3026-10-26T12:00:00+09:00" }
- match: { hits.hits.1.sort: [ 33349892400000 ] }
- match: { hits.hits.2._source.nested_field.0.date_field: "3025-10-26T12:00:00+09:00" }
- match: { hits.hits.2.sort: [ 33318356400000 ] }
- match: { hits.hits.3._source.nested_field.0.date_field: "3024-10-26T12:00:00+09:00" }
- match: { hits.hits.3.sort: [ 33286820400000 ] }
- match: { hits.hits.4._source.nested_field.0.date_field: "3023-10-26T12:00:00+09:00" }
- match: { hits.hits.4.sort: [ 33255198000000 ] }

# gte: now/h with the asc sort
- do:
search:
index: test
body:
size: 5
sort: [ { nested_field.date_field: { mode: max, order: asc, nested: { path: nested_field, filter: { bool: { filter: [ { range: { nested_field.date_field: { gte: now/h, time_zone: +09:00 } } } ] } } } } } ]
- match: { hits.total.value: 10 }
- length: { hits.hits: 5 }
- match: { hits.hits.0._index: test }
- match: { hits.hits.0._source.nested_field.0.date_field: "3023-10-26T12:00:00+09:00" }
- match: { hits.hits.0.sort: [ 33255198000000 ] }
- match: { hits.hits.1._source.nested_field.0.date_field: "3024-10-26T12:00:00+09:00" }
- match: { hits.hits.1.sort: [ 33286820400000 ] }
- match: { hits.hits.2._source.nested_field.0.date_field: "3025-10-26T12:00:00+09:00" }
- match: { hits.hits.2.sort: [ 33318356400000 ] }
- match: { hits.hits.3._source.nested_field.0.date_field: "3026-10-26T12:00:00+09:00" }
- match: { hits.hits.3.sort: [ 33349892400000 ] }
- match: { hits.hits.4._source.nested_field.0.date_field: "3027-10-26T12:00:00+09:00" }
- match: { hits.hits.4.sort: [ 33381428400000 ] }
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
- match: {hits.hits.0._source.timestamp: "2019-10-21 08:30:04.828733" }
- match: {hits.hits.0.sort: [1571646604828733000] }

# search_after with the sort
# search_after with the asc sort
- do:
search:
index: test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,14 +507,18 @@ private boolean canMatch(LeafReaderContext ctx) throws IOException {
}

private boolean canMatchSearchAfter(LeafReaderContext ctx) throws IOException {
if (searchContext.request() != null && searchContext.request().source() != null) {
if (searchContext.searchAfter() != null
&& searchContext.sort() != null
&& searchContext.request() != null
&& searchContext.request().source() != null) {
// Only applied on primary sort field and primary search_after.
FieldSortBuilder primarySortField = FieldSortBuilder.getPrimaryFieldSortOrNull(searchContext.request().source());
if (primarySortField != null) {
MinAndMax<?> minMax = FieldSortBuilder.getMinMaxOrNullForSegment(
this.searchContext.getQueryShardContext(),
ctx,
primarySortField
primarySortField,
searchContext.sort()

Check warning on line 521 in server/src/main/java/org/opensearch/search/internal/ContextIndexSearcher.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/search/internal/ContextIndexSearcher.java#L521

Added line #L521 was not covered by tests
);
return SearchService.canMatchSearchAfter(
searchContext.searchAfter(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,22 +611,32 @@ public static FieldSortBuilder getPrimaryFieldSortOrNull(SearchSourceBuilder sou
* and configurations return <code>null</code>.
*/
public static MinAndMax<?> getMinMaxOrNull(QueryShardContext context, FieldSortBuilder sortBuilder) throws IOException {
return getMinMaxOrNullInternal(context.getIndexReader(), context, sortBuilder);
return getMinMaxOrNullInternal(context.getIndexReader(), context, sortBuilder, null);
}

/**
* Return the {@link MinAndMax} indexed value for segment from the provided {@link FieldSortBuilder} or <code>null</code> if unknown.
* The value can be extracted on non-nested indexed mapped fields of type keyword, numeric or date, other fields
* and configurations return <code>null</code>.
*/
public static MinAndMax<?> getMinMaxOrNullForSegment(QueryShardContext context, LeafReaderContext ctx, FieldSortBuilder sortBuilder)
throws IOException {
return getMinMaxOrNullInternal(ctx.reader(), context, sortBuilder);
public static MinAndMax<?> getMinMaxOrNullForSegment(
QueryShardContext context,
LeafReaderContext ctx,
FieldSortBuilder sortBuilder,
SortAndFormats sort
) throws IOException {
return getMinMaxOrNullInternal(ctx.reader(), context, sortBuilder, sort);

Check warning on line 628 in server/src/main/java/org/opensearch/search/sort/FieldSortBuilder.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/search/sort/FieldSortBuilder.java#L628

Added line #L628 was not covered by tests
}

private static MinAndMax<?> getMinMaxOrNullInternal(IndexReader reader, QueryShardContext context, FieldSortBuilder sortBuilder)
throws IOException {
SortAndFormats sort = SortBuilder.buildSort(Collections.singletonList(sortBuilder), context).get();
private static MinAndMax<?> getMinMaxOrNullInternal(
IndexReader reader,
QueryShardContext context,
FieldSortBuilder sortBuilder,
SortAndFormats sort
) throws IOException {
if (sort == null) {
sort = SortBuilder.buildSort(Collections.singletonList(sortBuilder), context).get();
}
SortField sortField = sort.sort.getSort()[0];
if (sortField.getField() == null) {
return null;
Expand Down

0 comments on commit 5236b2f

Please sign in to comment.