From dfde04a808454a567e51f0f259b52ea0e686da9c Mon Sep 17 00:00:00 2001 From: gashutos Date: Sun, 19 Feb 2023 15:38:25 +0530 Subject: [PATCH 01/10] Adding numeric optimization support for all numeric types Signed-off-by: gashutos --- CHANGELOG.md | 1 + .../action/search/SearchPhaseController.java | 96 ++++++++ .../fielddata/IndexNumericFieldData.java | 119 ++------- .../IntValuesComparatorSource.java | 60 +++++ .../search/SearchPhaseControllerTests.java | 226 ++++++++++++++++-- 5 files changed, 380 insertions(+), 122 deletions(-) create mode 100644 server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e5c60bdc99db9..eb2b97af048d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Fix timeout error when adding a document to an index with extension running ([#6275](https://github.com/opensearch-project/OpenSearch/pull/6275)) - Handle translog upload during primary relocation for remote-backed indexes ([#5804](https://github.com/opensearch-project/OpenSearch/pull/5804)) - Batch translog sync/upload per x ms for remote-backed indexes ([#5854](https://github.com/opensearch-project/OpenSearch/pull/5854)) +- Enable sort optimization for all NumericTypes ([#6321](https://github.com/opensearch-project/OpenSearch/pull/6321) ### Dependencies - Update nebula-publishing-plugin to 19.2.0 ([#5704](https://github.com/opensearch-project/OpenSearch/pull/5704)) diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index d32e7753cd153..2ca9d2d0699d7 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -35,17 +35,22 @@ import com.carrotsearch.hppc.IntArrayList; import com.carrotsearch.hppc.ObjectObjectHashMap; +import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.Term; import org.apache.lucene.search.CollectionStatistics; +import org.apache.lucene.search.FieldComparator; import org.apache.lucene.search.FieldDoc; +import org.apache.lucene.search.LeafFieldComparator; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; +import org.apache.lucene.search.SortedNumericSortField; import org.apache.lucene.search.TermStatistics; import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.search.TotalHits; import org.apache.lucene.search.TotalHits.Relation; +import org.apache.lucene.search.comparators.NumericComparator; import org.apache.lucene.search.grouping.CollapseTopFieldDocs; import org.opensearch.common.breaker.CircuitBreaker; import org.opensearch.common.collect.HppcMaps; @@ -72,6 +77,7 @@ import org.opensearch.search.suggest.Suggest.Suggestion; import org.opensearch.search.suggest.completion.CompletionSuggestion; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -237,11 +243,13 @@ static TopDocs mergeTopDocs(Collection results, int topN, int from) { } else if (topDocs instanceof CollapseTopFieldDocs) { CollapseTopFieldDocs firstTopDocs = (CollapseTopFieldDocs) topDocs; final Sort sort = new Sort(firstTopDocs.fields); + applySortFieldWidening(sort); final CollapseTopFieldDocs[] shardTopDocs = results.toArray(new CollapseTopFieldDocs[numShards]); mergedTopDocs = CollapseTopFieldDocs.merge(sort, from, topN, shardTopDocs, false); } else if (topDocs instanceof TopFieldDocs) { TopFieldDocs firstTopDocs = (TopFieldDocs) topDocs; final Sort sort = new Sort(firstTopDocs.fields); + applySortFieldWidening(sort); final TopFieldDocs[] shardTopDocs = results.toArray(new TopFieldDocs[numShards]); mergedTopDocs = TopDocs.merge(sort, from, topN, shardTopDocs); } else { @@ -600,6 +608,94 @@ private static void validateMergeSortValueFormats(Collection getComparator(int numHits, boolean enableSkipping) { + return new NumericComparator( + delegate.getField(), + (Number) delegate.getMissingValue(), + delegate.getReverse(), + enableSkipping, + bytes + ) { + @Override + public int compare(int slot1, int slot2) { + throw new UnsupportedOperationException(); + } + + @Override + public Number value(int slot) { + throw new UnsupportedOperationException(); + } + + @Override + public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public int compareValues(Number first, Number second) { + if (first == null) { + if (second == null) { + return 0; + } else { + return -1; + } + } else if (second == null) { + return 1; + } else { + if (type == Type.LONG) { + return Long.compare(first.longValue(), second.longValue()); + } else { + return Double.compare(first.doubleValue(), second.doubleValue()); + } + } + } + }; + } + }; + } + /* * Returns the size of the requested top documents (from + size) */ diff --git a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java index 6fe79565a51e1..89d64341595b4 100644 --- a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java +++ b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java @@ -42,6 +42,7 @@ import org.opensearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested; import org.opensearch.index.fielddata.fieldcomparator.DoubleValuesComparatorSource; import org.opensearch.index.fielddata.fieldcomparator.FloatValuesComparatorSource; +import org.opensearch.index.fielddata.fieldcomparator.IntValuesComparatorSource; import org.opensearch.index.fielddata.fieldcomparator.LongValuesComparatorSource; import org.opensearch.search.DocValueFormat; import org.opensearch.search.MultiValueMode; @@ -65,76 +66,16 @@ public abstract class IndexNumericFieldData implements IndexFieldData results = generateQueryResults(nShards, suggestions, queryResultSize, false); - Optional first = results.asList().stream().findFirst(); - int from = 0, size = 0; - if (first.isPresent()) { - from = first.get().queryResult().from(); - size = first.get().queryResult().size(); + performSortDocs(results, queryResultSize); + } + + /** + * Test to verify merge shard results with SortField.Type.Int, document type Integer + */ + public void testSortIntFieldDocsMerge() { + List suggestions = new ArrayList<>(); + for (int i = 0; i < randomIntBetween(1, 5); i++) { + suggestions.add(new CompletionSuggestion(randomAlphaOfLength(randomIntBetween(1, 5)), randomIntBetween(1, 20), false)); } - int accumulatedLength = Math.min(queryResultSize, getTotalQueryHits(results)); - List reducedCompletionSuggestions = reducedSuggest(results); - for (Suggest.Suggestion suggestion : reducedCompletionSuggestions) { - int suggestionSize = suggestion.getEntries().get(0).getOptions().size(); - accumulatedLength += suggestionSize; + int nShards = randomIntBetween(1, 20); + int queryResultSize = randomBoolean() ? 0 : randomIntBetween(1, nShards * 2); + AtomicArray results = generateQueryResultsWithIntSortedField(nShards, suggestions, queryResultSize, false); + performSortDocs(results, queryResultSize); + } + + /** + * Test to verify merge shard results with different SortField.Type. + * Few shards with Int and few shards with Long + */ + public void testSortIntLongFieldDocsMerge() { + List suggestions = new ArrayList<>(); + for (int i = 0; i < randomIntBetween(1, 5); i++) { + suggestions.add(new CompletionSuggestion(randomAlphaOfLength(randomIntBetween(1, 5)), randomIntBetween(1, 20), false)); } - List topDocsList = new ArrayList<>(); - for (SearchPhaseResult result : results.asList()) { - QuerySearchResult queryResult = result.queryResult(); - TopDocs topDocs = queryResult.consumeTopDocs().topDocs; - SearchPhaseController.setShardIndex(topDocs, result.getShardIndex()); - topDocsList.add(topDocs); + int nShards = randomIntBetween(1, 20); + int queryResultSize = randomBoolean() ? 0 : randomIntBetween(1, nShards * 2); + AtomicArray results = generateQueryResultsWithIntLongSortedField(nShards, suggestions, queryResultSize, false); + performSortDocs(results, queryResultSize); + } + + /** + * Test to verify merge shard results with SortField.Type.Float, document type Float + */ + public void testSortFloatFieldDocsMerge() { + List suggestions = new ArrayList<>(); + for (int i = 0; i < randomIntBetween(1, 5); i++) { + suggestions.add(new CompletionSuggestion(randomAlphaOfLength(randomIntBetween(1, 5)), randomIntBetween(1, 20), false)); } - ScoreDoc[] sortedDocs = SearchPhaseController.sortDocs(true, topDocsList, from, size, reducedCompletionSuggestions).scoreDocs; - assertThat(sortedDocs.length, equalTo(accumulatedLength)); + int nShards = randomIntBetween(1, 20); + int queryResultSize = randomBoolean() ? 0 : randomIntBetween(1, nShards * 2); + AtomicArray results = generateQueryResultsWithFloatSortedField(nShards, suggestions, queryResultSize, false); + performSortDocs(results, queryResultSize); + } + + /** + * Test to verify merge shard results with different SortField.Type. + * Few shards with Float and few shards with Double + */ + public void testSortIntFloatDoubleFieldDocsMerge() { + List suggestions = new ArrayList<>(); + for (int i = 0; i < randomIntBetween(1, 5); i++) { + suggestions.add(new CompletionSuggestion(randomAlphaOfLength(randomIntBetween(1, 5)), randomIntBetween(1, 20), false)); + } + int nShards = randomIntBetween(1, 20); + int queryResultSize = randomBoolean() ? 0 : randomIntBetween(1, nShards * 2); + AtomicArray results = generateQueryResultsWithFloatDoubleSortedField( + nShards, + suggestions, + queryResultSize, + false + ); + performSortDocs(results, queryResultSize); } public void testSortDocsIsIdempotent() throws Exception { @@ -241,6 +285,30 @@ public void testSortDocsIsIdempotent() throws Exception { } } + private static void performSortDocs(AtomicArray results, int queryResultSize) { + Optional first = results.asList().stream().findFirst(); + int from = 0, size = 0; + if (first.isPresent()) { + from = first.get().queryResult().from(); + size = first.get().queryResult().size(); + } + int accumulatedLength = Math.min(queryResultSize, getTotalQueryHits(results)); + List reducedCompletionSuggestions = reducedSuggest(results); + for (Suggest.Suggestion suggestion : reducedCompletionSuggestions) { + int suggestionSize = suggestion.getEntries().get(0).getOptions().size(); + accumulatedLength += suggestionSize; + } + List topDocsList = new ArrayList<>(); + for (SearchPhaseResult result : results.asList()) { + QuerySearchResult queryResult = result.queryResult(); + TopDocs topDocs = queryResult.consumeTopDocs().topDocs; + SearchPhaseController.setShardIndex(topDocs, result.getShardIndex()); + topDocsList.add(topDocs); + } + ScoreDoc[] sortedDocs = SearchPhaseController.sortDocs(true, topDocsList, from, size, reducedCompletionSuggestions).scoreDocs; + assertThat(sortedDocs.length, equalTo(accumulatedLength)); + } + private AtomicArray generateSeededQueryResults( long seed, int nShards, @@ -389,6 +457,128 @@ private static AtomicArray generateQueryResults( return queryResults; } + private static AtomicArray generateQueryResultsWithIntSortedField( + int nShards, + List suggestions, + int searchHitsSize, + boolean useConstantScore + ) { + AtomicArray results = generateQueryResults(nShards, suggestions, searchHitsSize, false); + for (int i = 0; i < results.length(); i++) { + int nDocs = randomIntBetween(0, searchHitsSize); + float maxScore = 0; + final TopDocs topDocs = getIntTopFieldDocs(nDocs, useConstantScore); + results.get(i).queryResult().topDocs(new TopDocsAndMaxScore(topDocs, maxScore), new DocValueFormat[1]); + } + return results; + } + + private static AtomicArray generateQueryResultsWithFloatSortedField( + int nShards, + List suggestions, + int searchHitsSize, + boolean useConstantScore + ) { + AtomicArray results = generateQueryResults(nShards, suggestions, searchHitsSize, false); + for (int i = 0; i < results.length(); i++) { + int nDocs = randomIntBetween(0, searchHitsSize); + float maxScore = 0; + final TopDocs topDocs = getFloatTopFieldDocs(nDocs, useConstantScore); + results.get(i).queryResult().topDocs(new TopDocsAndMaxScore(topDocs, maxScore), new DocValueFormat[1]); + } + return results; + } + + private static AtomicArray generateQueryResultsWithIntLongSortedField( + int nShards, + List suggestions, + int searchHitsSize, + boolean useConstantScore + ) { + AtomicArray results = generateQueryResults(nShards, suggestions, searchHitsSize, false); + for (int i = 0; i < results.length(); i++) { + int nDocs = randomIntBetween(0, searchHitsSize); + float maxScore = 0; + final TopDocs topDocs; + if (i % 2 == 0) { + topDocs = getLongTopFieldDocs(nDocs, useConstantScore); + } else { + topDocs = getIntTopFieldDocs(nDocs, useConstantScore); + } + results.get(i).queryResult().topDocs(new TopDocsAndMaxScore(topDocs, maxScore), new DocValueFormat[1]); + } + return results; + } + + private static AtomicArray generateQueryResultsWithFloatDoubleSortedField( + int nShards, + List suggestions, + int searchHitsSize, + boolean useConstantScore + ) { + AtomicArray results = generateQueryResults(nShards, suggestions, searchHitsSize, false); + for (int i = 0; i < results.length(); i++) { + int nDocs = randomIntBetween(0, searchHitsSize); + float maxScore = 0; + final TopDocs topDocs; + if (i % 2 == 0) { + topDocs = getFloatTopFieldDocs(nDocs, useConstantScore); + } else { + topDocs = getDoubleTopFieldDocs(nDocs, useConstantScore); + } + results.get(i).queryResult().topDocs(new TopDocsAndMaxScore(topDocs, maxScore), new DocValueFormat[1]); + } + return results; + } + + private static TopFieldDocs getLongTopFieldDocs(int nDocs, boolean useConstantScore) { + FieldDoc[] fieldDocs = new FieldDoc[nDocs]; + SortField[] sortFields = { new SortedNumericSortField("field", SortField.Type.LONG, true) }; + float maxScore = 0; + for (int i = 0; i < nDocs; i++) { + float score = useConstantScore ? 1.0F : Math.abs(randomFloat()); + fieldDocs[i] = new FieldDoc(i, score, new Long[] { randomLong() }); + maxScore = Math.max(score, maxScore); + } + return new TopFieldDocs(new TotalHits(fieldDocs.length, TotalHits.Relation.EQUAL_TO), fieldDocs, sortFields); + } + + private static TopFieldDocs getFloatTopFieldDocs(int nDocs, boolean useConstantScore) { + FieldDoc[] fieldDocs = new FieldDoc[nDocs]; + SortField[] sortFields = { new SortedNumericSortField("field", SortField.Type.FLOAT, true) }; + float maxScore = 0; + for (int i = 0; i < nDocs; i++) { + float score = useConstantScore ? 1.0F : Math.abs(randomFloat()); + fieldDocs[i] = new FieldDoc(i, score, new Float[] { randomFloat() }); + maxScore = Math.max(score, maxScore); + } + return new TopFieldDocs(new TotalHits(fieldDocs.length, TotalHits.Relation.EQUAL_TO), fieldDocs, sortFields); + } + + private static TopFieldDocs getDoubleTopFieldDocs(int nDocs, boolean useConstantScore) { + FieldDoc[] fieldDocs = new FieldDoc[nDocs]; + SortField[] sortFields = { new SortedNumericSortField("field", SortField.Type.DOUBLE, true) }; + float maxScore = 0; + for (int i = 0; i < nDocs; i++) { + float score = useConstantScore ? 1.0F : Math.abs(randomFloat()); + fieldDocs[i] = new FieldDoc(i, score, new Double[] { randomDouble() }); + maxScore = Math.max(score, maxScore); + } + return new TopFieldDocs(new TotalHits(fieldDocs.length, TotalHits.Relation.EQUAL_TO), fieldDocs, sortFields); + } + + private static TopFieldDocs getIntTopFieldDocs(int nDocs, boolean useConstantScore) { + FieldDoc[] fieldDocs = new FieldDoc[nDocs]; + SortField[] sortFields = { new SortedNumericSortField("field", SortField.Type.INT, true) }; + float maxScore = 0; + for (int i = 0; i < nDocs; i++) { + float score = useConstantScore ? 1.0F : Math.abs(randomFloat()); + fieldDocs[i] = new FieldDoc(i, score, new Integer[] { randomInt() }); + maxScore = Math.max(score, maxScore); + } + return new TopFieldDocs(new TotalHits(fieldDocs.length, TotalHits.Relation.EQUAL_TO), fieldDocs, sortFields); + } + private static int getTotalQueryHits(AtomicArray results) { int resultCount = 0; for (SearchPhaseResult shardResult : results.asList()) { From 5915c85fb177f221d398023dc8e0e78406334044 Mon Sep 17 00:00:00 2001 From: gashutos Date: Wed, 22 Feb 2023 04:18:46 +0530 Subject: [PATCH 02/10] modifying CHANGELOG.md Signed-off-by: gashutos --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb2b97af048d5..f5446eb7d656e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,7 +101,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Fix timeout error when adding a document to an index with extension running ([#6275](https://github.com/opensearch-project/OpenSearch/pull/6275)) - Handle translog upload during primary relocation for remote-backed indexes ([#5804](https://github.com/opensearch-project/OpenSearch/pull/5804)) - Batch translog sync/upload per x ms for remote-backed indexes ([#5854](https://github.com/opensearch-project/OpenSearch/pull/5854)) -- Enable sort optimization for all NumericTypes ([#6321](https://github.com/opensearch-project/OpenSearch/pull/6321) +- Enable sort optimization for all NumericTypes ([#6464](https://github.com/opensearch-project/OpenSearch/pull/6464) ### Dependencies - Update nebula-publishing-plugin to 19.2.0 ([#5704](https://github.com/opensearch-project/OpenSearch/pull/5704)) From 4cc18f03f2f4b115a2930f7fbb32e8a0ba69ab89 Mon Sep 17 00:00:00 2001 From: gashutos Date: Wed, 22 Feb 2023 18:52:13 +0530 Subject: [PATCH 03/10] Handling multi-cluster scenario where SortField serialization was failing Signed-off-by: gashutos --- .../action/search/SearchPhaseController.java | 94 ++++------------ .../org/opensearch/common/lucene/Lucene.java | 5 +- .../sort/SortedWiderNumericSortField.java | 106 ++++++++++++++++++ 3 files changed, 130 insertions(+), 75 deletions(-) create mode 100644 server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index 2ca9d2d0699d7..031c556ebdaad 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -35,12 +35,9 @@ import com.carrotsearch.hppc.IntArrayList; import com.carrotsearch.hppc.ObjectObjectHashMap; -import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.Term; import org.apache.lucene.search.CollectionStatistics; -import org.apache.lucene.search.FieldComparator; import org.apache.lucene.search.FieldDoc; -import org.apache.lucene.search.LeafFieldComparator; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; @@ -50,7 +47,6 @@ import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.search.TotalHits; import org.apache.lucene.search.TotalHits.Relation; -import org.apache.lucene.search.comparators.NumericComparator; import org.apache.lucene.search.grouping.CollapseTopFieldDocs; import org.opensearch.common.breaker.CircuitBreaker; import org.opensearch.common.collect.HppcMaps; @@ -73,11 +69,11 @@ import org.opensearch.search.profile.ProfileShardResult; import org.opensearch.search.profile.SearchProfileShardResults; import org.opensearch.search.query.QuerySearchResult; +import org.opensearch.search.sort.SortedWiderNumericSortField; import org.opensearch.search.suggest.Suggest; import org.opensearch.search.suggest.Suggest.Suggestion; import org.opensearch.search.suggest.completion.CompletionSuggestion; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -243,14 +239,14 @@ static TopDocs mergeTopDocs(Collection results, int topN, int from) { } else if (topDocs instanceof CollapseTopFieldDocs) { CollapseTopFieldDocs firstTopDocs = (CollapseTopFieldDocs) topDocs; final Sort sort = new Sort(firstTopDocs.fields); - applySortFieldWidening(sort); final CollapseTopFieldDocs[] shardTopDocs = results.toArray(new CollapseTopFieldDocs[numShards]); + applySortFieldWidening(sort, shardTopDocs); mergedTopDocs = CollapseTopFieldDocs.merge(sort, from, topN, shardTopDocs, false); } else if (topDocs instanceof TopFieldDocs) { TopFieldDocs firstTopDocs = (TopFieldDocs) topDocs; final Sort sort = new Sort(firstTopDocs.fields); - applySortFieldWidening(sort); final TopFieldDocs[] shardTopDocs = results.toArray(new TopFieldDocs[numShards]); + applySortFieldWidening(sort, shardTopDocs); mergedTopDocs = TopDocs.merge(sort, from, topN, shardTopDocs); } else { final TopDocs[] shardTopDocs = results.toArray(new TopDocs[numShards]); @@ -618,82 +614,34 @@ private static void validateMergeSortValueFormats(Collection getComparator(int numHits, boolean enableSkipping) { - return new NumericComparator( - delegate.getField(), - (Number) delegate.getMissingValue(), - delegate.getReverse(), - enableSkipping, - bytes - ) { - @Override - public int compare(int slot1, int slot2) { - throw new UnsupportedOperationException(); - } - - @Override - public Number value(int slot) { - throw new UnsupportedOperationException(); - } - - @Override - public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public int compareValues(Number first, Number second) { - if (first == null) { - if (second == null) { - return 0; - } else { - return -1; - } - } else if (second == null) { - return 1; - } else { - if (type == Type.LONG) { - return Long.compare(first.longValue(), second.longValue()); - } else { - return Double.compare(first.doubleValue(), second.doubleValue()); - } - } - } - }; + private static boolean isSortWideningRequired(TopFieldDocs[] topFieldDocs, int sortFieldindex) { + for (int i = 0; i < topFieldDocs.length - 1; i++) { + if (topFieldDocs[i].fields[sortFieldindex] != topFieldDocs[i + 1].fields[sortFieldindex]) { + return true; } - }; + } + return false; } /* diff --git a/server/src/main/java/org/opensearch/common/lucene/Lucene.java b/server/src/main/java/org/opensearch/common/lucene/Lucene.java index a575f8622c151..d6eb5780f87da 100644 --- a/server/src/main/java/org/opensearch/common/lucene/Lucene.java +++ b/server/src/main/java/org/opensearch/common/lucene/Lucene.java @@ -93,6 +93,7 @@ import org.opensearch.index.analysis.AnalyzerScope; import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.fielddata.IndexFieldData; +import org.opensearch.search.sort.SortedWiderNumericSortField; import java.io.IOException; import java.math.BigInteger; @@ -599,8 +600,8 @@ public static void writeSortField(StreamOutput out, SortField sortField) throws SortField newSortField = new SortField(sortField.getField(), SortField.Type.STRING, sortField.getReverse()); newSortField.setMissingValue(sortField.getMissingValue()); sortField = newSortField; - } else if (sortField.getClass() == SortedNumericSortField.class) { - // for multi-valued sort field, we replace the SortedSetSortField with a simple SortField. + } else if (sortField.getClass() == SortedNumericSortField.class || sortField.getClass() == SortedWiderNumericSortField.class) { + // for multi-valued sort field, we replace the SortedNumericSortField/SortedWiderNumericSortField with a simple SortField. // It works because the sort field is only used to merge results from different shards. SortField newSortField = new SortField( sortField.getField(), diff --git a/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java new file mode 100644 index 0000000000000..72305c9fe6011 --- /dev/null +++ b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java @@ -0,0 +1,106 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.search.sort; + +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.search.FieldComparator; +import org.apache.lucene.search.LeafFieldComparator; +import org.apache.lucene.search.SortedNumericSelector; +import org.apache.lucene.search.SortedNumericSortField; +import org.apache.lucene.search.comparators.NumericComparator; + +import java.io.IOException; + +/** + * Sorted numeric field for wider sort types, + * to help sorting two different numeric types. + * + * @opensearch.internal + */ +public class SortedWiderNumericSortField extends SortedNumericSortField { + /** + * Creates a sort, possibly in reverse, specifying how the sort value from the document's set is + * selected. + * + * @param field Name of field to sort by. Must not be null. + * @param type Type of values + * @param reverse True if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + */ + public SortedWiderNumericSortField(String field, Type type, boolean reverse, SortedNumericSelector.Type selector) { + super(field, type, reverse, selector); + } + + /** + * Creates and return a comparator, which always converts Numeric to double + * and compare to support multi type comparison between numeric values + * @param numHits number of top hits the queue will store + * @param enableSkipping true if the comparator can skip documents via {@link + * LeafFieldComparator#competitiveIterator()} + * @return + */ + @Override + public FieldComparator getComparator(int numHits, boolean enableSkipping) { + return new NumericComparator(getField(), (Number) getMissingValue(), getReverse(), enableSkipping, Double.BYTES) { + @Override + public int compare(int slot1, int slot2) { + throw new UnsupportedOperationException(); + } + + @Override + public Number value(int slot) { + throw new UnsupportedOperationException(); + } + + @Override + public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public int compareValues(Number first, Number second) { + if (first == null) { + if (second == null) { + return 0; + } else { + return -1; + } + } else if (second == null) { + return 1; + } else { + return Double.compare(first.doubleValue(), second.doubleValue()); + } + } + }; + } +} From 4e2a4ad73feda0a6f5c2639da55f1053033beabd Mon Sep 17 00:00:00 2001 From: gashutos Date: Wed, 22 Feb 2023 19:17:55 +0530 Subject: [PATCH 04/10] Fixing javadoc errors Signed-off-by: gashutos --- .../org/opensearch/action/search/SearchPhaseController.java | 2 +- .../org/opensearch/search/sort/SortedWiderNumericSortField.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index 031c556ebdaad..9680d7a00c923 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -633,7 +633,7 @@ private static void applySortFieldWidening(Sort sort, TopFieldDocs[] topFieldDoc * field mapping type, accordingly it will decide to widen the sort fields. * @param topFieldDocs * @param sortFieldindex - * @return + * @return boolean */ private static boolean isSortWideningRequired(TopFieldDocs[] topFieldDocs, int sortFieldindex) { for (int i = 0; i < topFieldDocs.length - 1; i++) { diff --git a/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java index 72305c9fe6011..439da53171e36 100644 --- a/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java +++ b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java @@ -67,7 +67,7 @@ public SortedWiderNumericSortField(String field, Type type, boolean reverse, Sor * @param numHits number of top hits the queue will store * @param enableSkipping true if the comparator can skip documents via {@link * LeafFieldComparator#competitiveIterator()} - * @return + * @return NumericComparator */ @Override public FieldComparator getComparator(int numHits, boolean enableSkipping) { From aef5f857d11a5a4a293d4a6b4173bc6d6ea509e5 Mon Sep 17 00:00:00 2001 From: gashutos Date: Wed, 22 Feb 2023 21:37:45 +0530 Subject: [PATCH 05/10] Fixing nested sort integ tests Signed-off-by: gashutos --- .../index/fielddata/IndexNumericFieldData.java | 18 ++++++++++-------- .../search/sort/FieldSortBuilderTests.java | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java index 89d64341595b4..c042468e2d2a6 100644 --- a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java +++ b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java @@ -113,8 +113,6 @@ public final SortField sortField( Nested nested, boolean reverse ) { - XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, nested); - /* * Use a SortField with the custom comparator logic if required because * 1. The underlying data source needs it. @@ -126,6 +124,7 @@ public final SortField sortField( || nested != null || (sortMode != MultiValueMode.MAX && sortMode != MultiValueMode.MIN) || targetNumericType != getNumericType()) { + XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, nested, true); return new SortField(getFieldName(), source, reverse); } @@ -133,6 +132,7 @@ public final SortField sortField( ? SortedNumericSelector.Type.MAX : SortedNumericSelector.Type.MIN; SortField sortField = new SortedNumericSortField(getFieldName(), getNumericType().sortFieldType, reverse, selectorType); + XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, null, false); sortField.setMissingValue(source.missingObject(missingValue, reverse)); return sortField; } @@ -164,7 +164,7 @@ public final BucketedSort newBucketedSort( int bucketSize, BucketedSort.ExtraData extra ) { - return comparatorSource(targetNumericType, missingValue, sortMode, nested).newBucketedSort( + return comparatorSource(targetNumericType, missingValue, sortMode, nested, true).newBucketedSort( bigArrays, sortOrder, format, @@ -194,7 +194,8 @@ private XFieldComparatorSource comparatorSource( NumericType targetNumericType, @Nullable Object missingValue, MultiValueMode sortMode, - Nested nested + Nested nested, + boolean isCustomComparator ) { switch (targetNumericType) { case HALF_FLOAT: @@ -206,12 +207,13 @@ private XFieldComparatorSource comparatorSource( return dateComparatorSource(missingValue, sortMode, nested); case DATE_NANOSECONDS: return dateNanosComparatorSource(missingValue, sortMode, nested); - case LONG: - assert !targetNumericType.isFloatingPoint(); - return new LongValuesComparatorSource(this, missingValue, sortMode, nested); default: assert !targetNumericType.isFloatingPoint(); - return new IntValuesComparatorSource(this, missingValue, sortMode, nested); + if(isCustomComparator) { + return new LongValuesComparatorSource(this, missingValue, sortMode, nested); + } else { + return new IntValuesComparatorSource(this, missingValue, sortMode, nested); + } } } diff --git a/server/src/test/java/org/opensearch/search/sort/FieldSortBuilderTests.java b/server/src/test/java/org/opensearch/search/sort/FieldSortBuilderTests.java index 1d422f740c555..5bf60c50a1ab2 100644 --- a/server/src/test/java/org/opensearch/search/sort/FieldSortBuilderTests.java +++ b/server/src/test/java/org/opensearch/search/sort/FieldSortBuilderTests.java @@ -504,7 +504,7 @@ public void testGetMaxNumericSortValue() throws IOException { case INTEGER: int v2 = randomInt(); - values[i] = (long) v2; + values[i] = (int) v2; doc.add(new IntPoint(fieldName, v2)); break; @@ -528,13 +528,13 @@ public void testGetMaxNumericSortValue() throws IOException { case BYTE: byte v6 = randomByte(); - values[i] = (long) v6; + values[i] = (int) v6; doc.add(new IntPoint(fieldName, v6)); break; case SHORT: short v7 = randomShort(); - values[i] = (long) v7; + values[i] = (int) v7; doc.add(new IntPoint(fieldName, v7)); break; From 6f92394ed5b0b2fee2d8e06b012f13bc4cd46478 Mon Sep 17 00:00:00 2001 From: gashutos Date: Wed, 22 Feb 2023 22:24:14 +0530 Subject: [PATCH 06/10] Stremlining behaviour of custom comparator tests too Signed-off-by: gashutos --- .../fielddata/IndexNumericFieldData.java | 17 ++-- .../IntValuesComparatorSource.java | 90 ++++++++++++++++++- .../opensearch/search/sort/BucketedSort.java | 88 ++++++++++++++++++ .../search/nested/NestedSortingTests.java | 60 ++++++------- 4 files changed, 212 insertions(+), 43 deletions(-) diff --git a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java index c042468e2d2a6..151617224d026 100644 --- a/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java +++ b/server/src/main/java/org/opensearch/index/fielddata/IndexNumericFieldData.java @@ -113,6 +113,8 @@ public final SortField sortField( Nested nested, boolean reverse ) { + XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, nested); + /* * Use a SortField with the custom comparator logic if required because * 1. The underlying data source needs it. @@ -124,7 +126,6 @@ public final SortField sortField( || nested != null || (sortMode != MultiValueMode.MAX && sortMode != MultiValueMode.MIN) || targetNumericType != getNumericType()) { - XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, nested, true); return new SortField(getFieldName(), source, reverse); } @@ -132,7 +133,6 @@ public final SortField sortField( ? SortedNumericSelector.Type.MAX : SortedNumericSelector.Type.MIN; SortField sortField = new SortedNumericSortField(getFieldName(), getNumericType().sortFieldType, reverse, selectorType); - XFieldComparatorSource source = comparatorSource(targetNumericType, missingValue, sortMode, null, false); sortField.setMissingValue(source.missingObject(missingValue, reverse)); return sortField; } @@ -164,7 +164,7 @@ public final BucketedSort newBucketedSort( int bucketSize, BucketedSort.ExtraData extra ) { - return comparatorSource(targetNumericType, missingValue, sortMode, nested, true).newBucketedSort( + return comparatorSource(targetNumericType, missingValue, sortMode, nested).newBucketedSort( bigArrays, sortOrder, format, @@ -194,8 +194,7 @@ private XFieldComparatorSource comparatorSource( NumericType targetNumericType, @Nullable Object missingValue, MultiValueMode sortMode, - Nested nested, - boolean isCustomComparator + Nested nested ) { switch (targetNumericType) { case HALF_FLOAT: @@ -207,13 +206,11 @@ private XFieldComparatorSource comparatorSource( return dateComparatorSource(missingValue, sortMode, nested); case DATE_NANOSECONDS: return dateNanosComparatorSource(missingValue, sortMode, nested); + case LONG: + return new LongValuesComparatorSource(this, missingValue, sortMode, nested); default: assert !targetNumericType.isFloatingPoint(); - if(isCustomComparator) { - return new LongValuesComparatorSource(this, missingValue, sortMode, nested); - } else { - return new IntValuesComparatorSource(this, missingValue, sortMode, nested); - } + return new IntValuesComparatorSource(this, missingValue, sortMode, nested); } } diff --git a/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java b/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java index 0c154cf62579c..c938de167de40 100644 --- a/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java +++ b/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java @@ -24,7 +24,6 @@ * specific language governing permissions and limitations * under the License. */ - /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. @@ -32,17 +31,35 @@ package org.opensearch.index.fielddata.fieldcomparator; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.search.FieldComparator; +import org.apache.lucene.search.LeafFieldComparator; import org.apache.lucene.search.SortField; +import org.apache.lucene.search.comparators.IntComparator; +import org.apache.lucene.util.BitSet; import org.opensearch.common.Nullable; +import org.opensearch.common.util.BigArrays; +import org.opensearch.index.fielddata.FieldData; +import org.opensearch.index.fielddata.IndexFieldData; import org.opensearch.index.fielddata.IndexNumericFieldData; +import org.opensearch.search.DocValueFormat; import org.opensearch.search.MultiValueMode; +import org.opensearch.search.sort.BucketedSort; +import org.opensearch.search.sort.SortOrder; + +import java.io.IOException; /** * Comparator source for int values. * * @opensearch.internal */ -public class IntValuesComparatorSource extends LongValuesComparatorSource { +public class IntValuesComparatorSource extends IndexFieldData.XFieldComparatorSource { + + private final IndexNumericFieldData indexFieldData; public IntValuesComparatorSource( IndexNumericFieldData indexFieldData, @@ -50,11 +67,78 @@ public IntValuesComparatorSource( MultiValueMode sortMode, Nested nested ) { - super(indexFieldData, missingValue, sortMode, nested); + super(missingValue, sortMode, nested); + this.indexFieldData = indexFieldData; } @Override public SortField.Type reducedType() { return SortField.Type.INT; } + + private NumericDocValues getNumericDocValues(LeafReaderContext context, int missingValue) throws IOException { + final SortedNumericDocValues values = indexFieldData.load(context).getLongValues(); + if (nested == null) { + return FieldData.replaceMissing(sortMode.select(values), missingValue); + } + final BitSet rootDocs = nested.rootDocs(context); + final DocIdSetIterator innerDocs = nested.innerDocs(context); + final int maxChildren = nested.getNestedSort() != null ? nested.getNestedSort().getMaxChildren() : Integer.MAX_VALUE; + return sortMode.select(values, missingValue, rootDocs, innerDocs, context.reader().maxDoc(), maxChildren); + } + + @Override + public FieldComparator newComparator(String fieldname, int numHits, boolean enableSkipping, boolean reversed) { + assert indexFieldData == null || fieldname.equals(indexFieldData.getFieldName()); + + final int iMissingValue = (Integer) missingObject(missingValue, reversed); + // NOTE: it's important to pass null as a missing value in the constructor so that + // the comparator doesn't check docsWithField since we replace missing values in select() + return new IntComparator(numHits, null, null, reversed, false) { + @Override + public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { + return new IntLeafComparator(context) { + @Override + protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException { + return IntValuesComparatorSource.this.getNumericDocValues(context, iMissingValue); + } + }; + } + }; + } + + @Override + public BucketedSort newBucketedSort( + BigArrays bigArrays, + SortOrder sortOrder, + DocValueFormat format, + int bucketSize, + BucketedSort.ExtraData extra + ) { + return new BucketedSort.ForInts(bigArrays, sortOrder, format, bucketSize, extra) { + private final int iMissingValue = (Integer) missingObject(missingValue, sortOrder == SortOrder.DESC); + + @Override + public Leaf forLeaf(LeafReaderContext ctx) throws IOException { + return new Leaf(ctx) { + private final NumericDocValues docValues = getNumericDocValues(ctx, iMissingValue); + private long docValue; + + @Override + protected boolean advanceExact(int doc) throws IOException { + if (docValues.advanceExact(doc)) { + docValue = docValues.longValue(); + return true; + } + return false; + } + + @Override + protected int docValue() { + return (int) docValue; + } + }; + } + }; + } } diff --git a/server/src/main/java/org/opensearch/search/sort/BucketedSort.java b/server/src/main/java/org/opensearch/search/sort/BucketedSort.java index 9266469db2b05..aa8cff7c963ed 100644 --- a/server/src/main/java/org/opensearch/search/sort/BucketedSort.java +++ b/server/src/main/java/org/opensearch/search/sort/BucketedSort.java @@ -42,6 +42,7 @@ import org.opensearch.common.util.BitArray; import org.opensearch.common.util.DoubleArray; import org.opensearch.common.util.FloatArray; +import org.opensearch.common.util.IntArray; import org.opensearch.common.util.LongArray; import org.opensearch.search.DocValueFormat; @@ -756,4 +757,91 @@ protected final boolean docBetterThan(long index) { } } } + + /** + * Superclass for implementations of {@linkplain BucketedSort} for {@code int} keys. + */ + public abstract static class ForInts extends BucketedSort { + private IntArray values = bigArrays.newIntArray(1, false); + + public ForInts(BigArrays bigArrays, SortOrder sortOrder, DocValueFormat format, int bucketSize, ExtraData extra) { + super(bigArrays, sortOrder, format, bucketSize, extra); + initGatherOffsets(); + } + + @Override + public final boolean needsScores() { + return false; + } + + @Override + protected final BigArray values() { + return values; + } + + @Override + protected final void growValues(long minSize) { + values = bigArrays.grow(values, minSize); + } + + @Override + protected final int getNextGatherOffset(long rootIndex) { + return (int) values.get(rootIndex); + } + + @Override + protected final void setNextGatherOffset(long rootIndex, int offset) { + values.set(rootIndex, offset); + } + + @Override + protected final SortValue getValue(long index) { + return SortValue.from(values.get(index)); + } + + @Override + protected final boolean betterThan(long lhs, long rhs) { + return getOrder().reverseMul() * Integer.compare(values.get(lhs), values.get(rhs)) < 0; + } + + @Override + protected final void swap(long lhs, long rhs) { + int tmp = values.get(lhs); + values.set(lhs, values.get(rhs)); + values.set(rhs, tmp); + } + + /** + * Leaf for bucketed sort + * + * @opensearch.internal + */ + protected abstract class Leaf extends BucketedSort.Leaf { + protected Leaf(LeafReaderContext ctx) { + super(ctx); + } + + /** + * Return the value for of this sort for the document to which + * we just {@link #advanceExact(int) moved}. This should be fast + * because it is called twice per competitive hit when in heap + * mode, once for {@link #docBetterThan(long)} and once + * for {@link #setIndexToDocValue(long)}. + */ + protected abstract int docValue(); + + @Override + public final void setScorer(Scorable scorer) {} + + @Override + protected final void setIndexToDocValue(long index) { + values.set(index, docValue()); + } + + @Override + protected final boolean docBetterThan(long index) { + return getOrder().reverseMul() * Integer.compare(docValue(), values.get(index)) < 0; + } + } + } } diff --git a/server/src/test/java/org/opensearch/index/search/nested/NestedSortingTests.java b/server/src/test/java/org/opensearch/index/search/nested/NestedSortingTests.java index 79c0044a0ceb0..7f130680f83e5 100644 --- a/server/src/test/java/org/opensearch/index/search/nested/NestedSortingTests.java +++ b/server/src/test/java/org/opensearch/index/search/nested/NestedSortingTests.java @@ -645,15 +645,15 @@ public void testMultiLevelNestedSorting() throws IOException { TopFieldDocs topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(5L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(87)); assertThat(searcher.doc(topFields.scoreDocs[2].doc).get("_id"), equalTo("1")); - assertThat(((FieldDoc) topFields.scoreDocs[2]).fields[0], equalTo(234L)); + assertThat(((FieldDoc) topFields.scoreDocs[2]).fields[0], equalTo(234)); assertThat(searcher.doc(topFields.scoreDocs[3].doc).get("_id"), equalTo("3")); - assertThat(((FieldDoc) topFields.scoreDocs[3]).fields[0], equalTo(976L)); + assertThat(((FieldDoc) topFields.scoreDocs[3]).fields[0], equalTo(976)); assertThat(searcher.doc(topFields.scoreDocs[4].doc).get("_id"), equalTo("5")); - assertThat(((FieldDoc) topFields.scoreDocs[4]).fields[0], equalTo(Long.MAX_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[4]).fields[0], equalTo(Integer.MAX_VALUE)); // Specific genre { @@ -661,25 +661,25 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76)); queryBuilder = new TermQueryBuilder("genre", "science fiction"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("1")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(234L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(234)); queryBuilder = new TermQueryBuilder("genre", "horror"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("3")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976)); queryBuilder = new TermQueryBuilder("genre", "cooking"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87)); } // reverse sort order @@ -689,15 +689,15 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(5L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("3")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("1")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(849L)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(849)); assertThat(searcher.doc(topFields.scoreDocs[2].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[2]).fields[0], equalTo(180L)); + assertThat(((FieldDoc) topFields.scoreDocs[2]).fields[0], equalTo(180)); assertThat(searcher.doc(topFields.scoreDocs[3].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[3]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[3]).fields[0], equalTo(76)); assertThat(searcher.doc(topFields.scoreDocs[4].doc).get("_id"), equalTo("5")); - assertThat(((FieldDoc) topFields.scoreDocs[4]).fields[0], equalTo(Long.MIN_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[4]).fields[0], equalTo(Integer.MIN_VALUE)); } // Specific genre and reverse sort order @@ -706,25 +706,25 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76)); queryBuilder = new TermQueryBuilder("genre", "science fiction"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("1")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(849L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(849)); queryBuilder = new TermQueryBuilder("genre", "horror"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("3")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(976)); queryBuilder = new TermQueryBuilder("genre", "cooking"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(180L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(180)); } // Nested filter + query @@ -737,17 +737,17 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(new NestedQueryBuilder("chapters", queryBuilder, ScoreMode.None), sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(2L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(87)); sortBuilder.order(SortOrder.DESC); topFields = search(new NestedQueryBuilder("chapters", queryBuilder, ScoreMode.None), sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(2L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(76)); } // Multiple Nested filters + query @@ -765,17 +765,17 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(new NestedQueryBuilder("chapters", queryBuilder, ScoreMode.None), sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(2L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(Long.MAX_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(Integer.MAX_VALUE)); sortBuilder.order(SortOrder.DESC); topFields = search(new NestedQueryBuilder("chapters", queryBuilder, ScoreMode.None), sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(2L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87)); assertThat(searcher.doc(topFields.scoreDocs[1].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(Long.MIN_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[1]).fields[0], equalTo(Integer.MIN_VALUE)); } // Nested filter + Specific genre @@ -790,25 +790,25 @@ public void testMultiLevelNestedSorting() throws IOException { topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("2")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(76)); queryBuilder = new TermQueryBuilder("genre", "science fiction"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("1")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(Long.MAX_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(Integer.MAX_VALUE)); queryBuilder = new TermQueryBuilder("genre", "horror"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("3")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(Long.MAX_VALUE)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(Integer.MAX_VALUE)); queryBuilder = new TermQueryBuilder("genre", "cooking"); topFields = search(queryBuilder, sortBuilder, queryShardContext, searcher); assertThat(topFields.totalHits.value, equalTo(1L)); assertThat(searcher.doc(topFields.scoreDocs[0].doc).get("_id"), equalTo("4")); - assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87L)); + assertThat(((FieldDoc) topFields.scoreDocs[0]).fields[0], equalTo(87)); } searcher.getIndexReader().close(); From 007d90aa7833fa4a57bb9525645c8b3ceebdac13 Mon Sep 17 00:00:00 2001 From: gashutos Date: Thu, 23 Feb 2023 03:20:47 +0530 Subject: [PATCH 07/10] Adding more integ tests for IntValuesComparatorSource & fixing few ITs Signed-off-by: gashutos --- .../org/opensearch/index/IndexSortIT.java | 4 +- .../opensearch/search/sort/BucketedSort.java | 2 +- .../opensearch/common/lucene/LuceneTests.java | 12 ++- .../search/sort/BucketedSortForIntsTests.java | 77 +++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 server/src/test/java/org/opensearch/search/sort/BucketedSortForIntsTests.java diff --git a/server/src/internalClusterTest/java/org/opensearch/index/IndexSortIT.java b/server/src/internalClusterTest/java/org/opensearch/index/IndexSortIT.java index e06a2f91ae91a..d547ded8152dd 100644 --- a/server/src/internalClusterTest/java/org/opensearch/index/IndexSortIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/index/IndexSortIT.java @@ -81,8 +81,8 @@ private static XContentBuilder createTestMapping() { public void testIndexSort() { SortField dateSort = new SortedNumericSortField("date", SortField.Type.LONG, false); dateSort.setMissingValue(Long.MAX_VALUE); - SortField numericSort = new SortedNumericSortField("numeric_dv", SortField.Type.LONG, false); - numericSort.setMissingValue(Long.MAX_VALUE); + SortField numericSort = new SortedNumericSortField("numeric_dv", SortField.Type.INT, false); + numericSort.setMissingValue(Integer.MAX_VALUE); SortField keywordSort = new SortedSetSortField("keyword_dv", false); keywordSort.setMissingValue(SortField.STRING_LAST); Sort indexSort = new Sort(dateSort, numericSort, keywordSort); diff --git a/server/src/main/java/org/opensearch/search/sort/BucketedSort.java b/server/src/main/java/org/opensearch/search/sort/BucketedSort.java index aa8cff7c963ed..a075b6567fe2d 100644 --- a/server/src/main/java/org/opensearch/search/sort/BucketedSort.java +++ b/server/src/main/java/org/opensearch/search/sort/BucketedSort.java @@ -786,7 +786,7 @@ protected final void growValues(long minSize) { @Override protected final int getNextGatherOffset(long rootIndex) { - return (int) values.get(rootIndex); + return values.get(rootIndex); } @Override diff --git a/server/src/test/java/org/opensearch/common/lucene/LuceneTests.java b/server/src/test/java/org/opensearch/common/lucene/LuceneTests.java index 97c192ecd9660..e7756cbd96734 100644 --- a/server/src/test/java/org/opensearch/common/lucene/LuceneTests.java +++ b/server/src/test/java/org/opensearch/common/lucene/LuceneTests.java @@ -87,6 +87,7 @@ import org.opensearch.index.fielddata.fieldcomparator.BytesRefFieldComparatorSource; import org.opensearch.index.fielddata.fieldcomparator.DoubleValuesComparatorSource; import org.opensearch.index.fielddata.fieldcomparator.FloatValuesComparatorSource; +import org.opensearch.index.fielddata.fieldcomparator.IntValuesComparatorSource; import org.opensearch.index.fielddata.fieldcomparator.LongValuesComparatorSource; import org.opensearch.search.MultiValueMode; import org.opensearch.test.OpenSearchTestCase; @@ -753,7 +754,7 @@ private static Tuple randomSortFieldCustomComparatorSource IndexFieldData.XFieldComparatorSource comparatorSource; boolean reverse = randomBoolean(); Object missingValue = null; - switch (randomIntBetween(0, 3)) { + switch (randomIntBetween(0, 4)) { case 0: comparatorSource = new LongValuesComparatorSource( null, @@ -787,6 +788,15 @@ private static Tuple randomSortFieldCustomComparatorSource ); missingValue = comparatorSource.missingValue(reverse); break; + case 4: + comparatorSource = new IntValuesComparatorSource( + null, + randomBoolean() ? randomInt() : null, + randomFrom(MultiValueMode.values()), + null + ); + missingValue = comparatorSource.missingValue(reverse); + break; default: throw new UnsupportedOperationException(); } diff --git a/server/src/test/java/org/opensearch/search/sort/BucketedSortForIntsTests.java b/server/src/test/java/org/opensearch/search/sort/BucketedSortForIntsTests.java new file mode 100644 index 0000000000000..c3e0475685001 --- /dev/null +++ b/server/src/test/java/org/opensearch/search/sort/BucketedSortForIntsTests.java @@ -0,0 +1,77 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.search.sort; + +import org.apache.lucene.index.LeafReaderContext; +import org.opensearch.search.DocValueFormat; + +public class BucketedSortForIntsTests extends BucketedSortTestCase { + @Override + public BucketedSort.ForInts build( + SortOrder sortOrder, + DocValueFormat format, + int bucketSize, + BucketedSort.ExtraData extra, + double[] values + ) { + return new BucketedSort.ForInts(bigArrays(), sortOrder, format, bucketSize, extra) { + @Override + public Leaf forLeaf(LeafReaderContext ctx) { + return new Leaf(ctx) { + int index = -1; + + @Override + protected boolean advanceExact(int doc) { + index = doc; + return doc < values.length; + } + + @Override + protected int docValue() { + return (int) values[index]; + } + }; + } + }; + } + + @Override + protected SortValue expectedSortValue(double v) { + return SortValue.from((long) v); + } + + @Override + protected double randomValue() { + return randomIntBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); + } +} From 7ce9b400b801b5094b37ed0d05267bedca42c6f0 Mon Sep 17 00:00:00 2001 From: gashutos Date: Thu, 23 Feb 2023 14:22:11 +0530 Subject: [PATCH 08/10] Fixing few more integ tests Signed-off-by: gashutos --- .../search/searchafter/SearchAfterIT.java | 14 ++++++-------- .../action/search/SearchPhaseController.java | 4 ---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/server/src/internalClusterTest/java/org/opensearch/search/searchafter/SearchAfterIT.java b/server/src/internalClusterTest/java/org/opensearch/search/searchafter/SearchAfterIT.java index 2c98154115bb9..2a662c9dda088 100644 --- a/server/src/internalClusterTest/java/org/opensearch/search/searchafter/SearchAfterIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/search/searchafter/SearchAfterIT.java @@ -382,24 +382,22 @@ private void createIndexMappingsFromObjectType(String indexName, List ty ensureGreen(); } - // Convert Integer, Short, Byte and Boolean to Long in order to match the conversion done + // Convert Integer, Short, Byte and Boolean to Int in order to match the conversion done // by the internal hits when populating the sort values. private List convertSortValues(List sortValues) { List converted = new ArrayList<>(); for (int i = 0; i < sortValues.size(); i++) { Object from = sortValues.get(i); - if (from instanceof Integer) { - converted.add(((Integer) from).longValue()); - } else if (from instanceof Short) { - converted.add(((Short) from).longValue()); + if (from instanceof Short) { + converted.add(((Short) from).intValue()); } else if (from instanceof Byte) { - converted.add(((Byte) from).longValue()); + converted.add(((Byte) from).intValue()); } else if (from instanceof Boolean) { boolean b = (boolean) from; if (b) { - converted.add(1L); + converted.add(1); } else { - converted.add(0L); + converted.add(0); } } else { converted.add(from); diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index 9680d7a00c923..a97e4037fbe76 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -612,7 +612,6 @@ private static void validateMergeSortValueFormats(Collection Date: Thu, 16 Mar 2023 01:00:20 +0530 Subject: [PATCH 09/10] Streamlining applySortWidening method with CreateSort and avoid modifying cteated objects of sort Signed-off-by: gashutos --- .../action/search/SearchPhaseController.java | 25 +++++++++++-------- .../IntValuesComparatorSource.java | 6 ++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index a97e4037fbe76..5fa26a7e4a3ee 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -237,16 +237,12 @@ static TopDocs mergeTopDocs(Collection results, int topN, int from) { if (numShards == 1 && from == 0) { // only one shard and no pagination we can just return the topDocs as we got them. return topDocs; } else if (topDocs instanceof CollapseTopFieldDocs) { - CollapseTopFieldDocs firstTopDocs = (CollapseTopFieldDocs) topDocs; - final Sort sort = new Sort(firstTopDocs.fields); final CollapseTopFieldDocs[] shardTopDocs = results.toArray(new CollapseTopFieldDocs[numShards]); - applySortFieldWidening(sort, shardTopDocs); + final Sort sort = createSort(shardTopDocs); mergedTopDocs = CollapseTopFieldDocs.merge(sort, from, topN, shardTopDocs, false); } else if (topDocs instanceof TopFieldDocs) { - TopFieldDocs firstTopDocs = (TopFieldDocs) topDocs; - final Sort sort = new Sort(firstTopDocs.fields); final TopFieldDocs[] shardTopDocs = results.toArray(new TopFieldDocs[numShards]); - applySortFieldWidening(sort, shardTopDocs); + final Sort sort = createSort(shardTopDocs); mergedTopDocs = TopDocs.merge(sort, from, topN, shardTopDocs); } else { final TopDocs[] shardTopDocs = results.toArray(new TopDocs[numShards]); @@ -605,6 +601,7 @@ private static void validateMergeSortValueFormats(Collection Date: Tue, 28 Mar 2023 00:56:25 +0530 Subject: [PATCH 10/10] Correcting licence header Signed-off-by: gashutos --- .../action/search/SearchPhaseController.java | 2 +- .../IntValuesComparatorSource.java | 18 ------------------ .../sort/SortedWiderNumericSortField.java | 19 ------------------- 3 files changed, 1 insertion(+), 38 deletions(-) diff --git a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java index 5fa26a7e4a3ee..3f4f7c2b92512 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/opensearch/action/search/SearchPhaseController.java @@ -615,7 +615,7 @@ private static Sort createSort(TopFieldDocs[] topFieldDocs) { final SortField[] newFields = new SortField[firstTopDocFields.length]; for (int i = 0; i < firstTopDocFields.length; i++) { - if (isSortWideningRequired(topFieldDocs, i) && firstTopDocFields[i] instanceof SortedNumericSortField) { + if (firstTopDocFields[i] instanceof SortedNumericSortField && isSortWideningRequired(topFieldDocs, i)) { final SortedNumericSortField delegate = (SortedNumericSortField) firstTopDocFields[i]; newFields[i] = new SortedWiderNumericSortField( delegate.getField(), diff --git a/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java b/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java index a0803e7f40eef..90afa5fc64c29 100644 --- a/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java +++ b/server/src/main/java/org/opensearch/index/fielddata/fieldcomparator/IntValuesComparatorSource.java @@ -6,24 +6,6 @@ * compatible open source license. */ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. diff --git a/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java index 439da53171e36..2caacf33fcdcf 100644 --- a/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java +++ b/server/src/main/java/org/opensearch/search/sort/SortedWiderNumericSortField.java @@ -6,25 +6,6 @@ * compatible open source license. */ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details.