diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search/340_doc_values_field.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/search/340_doc_values_field.yml index eed57ab3d93ce..e249f2bb2a6ee 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/search/340_doc_values_field.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search/340_doc_values_field.yml @@ -305,6 +305,17 @@ - match: { hits.total: 2 } + - do: + search: + rest_total_hits_as_int: true + index: test-iodvq + body: + query: + terms: + boolean: [true, false] + + - match: { hits.total: 3 } + - do: search: rest_total_hits_as_int: true @@ -665,13 +676,13 @@ - match: {hits.total: 1} - do: - search: - rest_total_hits_as_int: true - index: test-index - body: - query: - term: - boolean: true + search: + rest_total_hits_as_int: true + index: test-index + body: + query: + term: + boolean: true - match: { hits.total: 2 } @@ -775,6 +786,17 @@ - match: { hits.total: 2 } + - do: + search: + rest_total_hits_as_int: true + index: test-index + body: + query: + terms: + boolean: [true, false] + + - match: { hits.total: 3 } + - do: search: rest_total_hits_as_int: true @@ -1235,6 +1257,17 @@ - match: { hits.total: 2 } + - do: + search: + rest_total_hits_as_int: true + index: test-doc-values + body: + query: + terms: + boolean: [true, false] + + - match: { hits.total: 3 } + - do: search: rest_total_hits_as_int: true diff --git a/server/src/main/java/org/opensearch/index/mapper/BooleanFieldMapper.java b/server/src/main/java/org/opensearch/index/mapper/BooleanFieldMapper.java index b3112a6002d84..3ea70800d0763 100644 --- a/server/src/main/java/org/opensearch/index/mapper/BooleanFieldMapper.java +++ b/server/src/main/java/org/opensearch/index/mapper/BooleanFieldMapper.java @@ -40,10 +40,9 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.IndexOrDocValuesQuery; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermInSetQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.util.BytesRef; @@ -284,27 +283,18 @@ public Query termQuery(Object value, QueryShardContext context) { @Override public Query termsQuery(List values, QueryShardContext context) { failIfNotIndexedAndNoDocValues(); - boolean seenTrue = false; - boolean seenFalse = false; - for (Object value : values) { - if (Values.TRUE.equals(indexedValueForSearch(value))) { - seenTrue = true; - } else if (Values.FALSE.equals(indexedValueForSearch(value))) { - seenFalse = true; - } else { - return new MatchNoDocsQuery("Values did not contain True or False"); - } - } - if (seenTrue) { - if (seenFalse) { - return new MatchAllDocsQuery(); + if (!isSearchable()) { + long[] v = new long[values.size()]; + for (int i = 0; i < v.length; i++) { + v[i] = Values.TRUE.bytesEquals(indexedValueForSearch(values.get(i))) ? 1 : 0; } - return termQuery("true", context); + return SortedNumericDocValuesField.newSlowSetQuery(name(), v); } - if (seenFalse) { - return termQuery("false", context); + BytesRef[] bytesRefs = new BytesRef[values.size()]; + for (int i = 0; i < bytesRefs.length; i++) { + bytesRefs[i] = indexedValueForSearch(values.get(i)); } - return new MatchNoDocsQuery("Values did not contain True or False"); + return new TermInSetQuery(name(), List.of(bytesRefs)); } diff --git a/server/src/test/java/org/opensearch/index/mapper/BooleanFieldMapperTests.java b/server/src/test/java/org/opensearch/index/mapper/BooleanFieldMapperTests.java index c0415c92b6997..5392bd6c358d3 100644 --- a/server/src/test/java/org/opensearch/index/mapper/BooleanFieldMapperTests.java +++ b/server/src/test/java/org/opensearch/index/mapper/BooleanFieldMapperTests.java @@ -32,14 +32,12 @@ package org.opensearch.index.mapper; -import org.apache.lucene.document.SortedNumericDocValuesField; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.SortedNumericDocValues; import org.apache.lucene.index.Term; import org.apache.lucene.search.BoostQuery; -import org.apache.lucene.search.IndexOrDocValuesQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; import org.opensearch.common.xcontent.XContentFactory; @@ -208,13 +206,7 @@ public void testBoosts() throws Exception { })); MappedFieldType ft = mapperService.fieldType("field"); - assertEquals( - new IndexOrDocValuesQuery( - new BoostQuery(new TermQuery(new Term("field", "T")), 2.0f), - SortedNumericDocValuesField.newSlowExactQuery("field", 1) - ), - ft.termQuery("true", null) - ); + assertEquals(new BoostQuery(new TermQuery(new Term("field", "T")), 2.0f), ft.termQuery("true", null)); assertParseMaximalWarnings(); } @@ -235,16 +227,6 @@ public void testIndexedValueForSearch() throws Exception { BooleanFieldMapper.Values.FALSE ); - assertEquals( - new BooleanFieldMapper.BooleanFieldType("bool").indexedValueForSearch(new BytesRef("T")), - BooleanFieldMapper.Values.TRUE - ); - - assertEquals( - new BooleanFieldMapper.BooleanFieldType("bool").indexedValueForSearch(new BytesRef("F")), - BooleanFieldMapper.Values.FALSE - ); - IllegalArgumentException e = expectThrows( IllegalArgumentException.class, () -> new BooleanFieldMapper.BooleanFieldType("bool").indexedValueForSearch(new BytesRef("random")) diff --git a/server/src/test/java/org/opensearch/index/mapper/BooleanFieldTypeTests.java b/server/src/test/java/org/opensearch/index/mapper/BooleanFieldTypeTests.java index d5eda3b7042b3..6d077b1b188b4 100644 --- a/server/src/test/java/org/opensearch/index/mapper/BooleanFieldTypeTests.java +++ b/server/src/test/java/org/opensearch/index/mapper/BooleanFieldTypeTests.java @@ -34,8 +34,7 @@ import org.apache.lucene.document.SortedNumericDocValuesField; import org.apache.lucene.index.Term; import org.apache.lucene.search.BoostQuery; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.MatchNoDocsQuery; +import org.apache.lucene.search.TermInSetQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; @@ -43,6 +42,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Stream; public class BooleanFieldTypeTests extends FieldTypeTestCase { @@ -82,17 +82,21 @@ public void testTermQuery() { public void testTermsQuery() { MappedFieldType ft = new BooleanFieldMapper.BooleanFieldType("field"); - BooleanFieldMapper.BooleanFieldType booleanFieldType = new BooleanFieldMapper.BooleanFieldType("field"); List terms = new ArrayList<>(); terms.add(new BytesRef("true")); terms.add(new BytesRef("false")); - assertEquals(new MatchAllDocsQuery(), ft.termsQuery(terms, null)); + assertEquals(new TermInSetQuery("field", List.of(new BytesRef("T"), newBytesRef("F"))), ft.termsQuery(terms, null)); List newTerms = new ArrayList<>(); newTerms.add(new BytesRef("true")); - assertEquals(new TermQuery(new Term("field", "T")), ft.termsQuery(newTerms, null)); + assertEquals(new TermInSetQuery("field", List.of(new BytesRef("T"))), ft.termsQuery(newTerms, null)); - assertEquals(new MatchNoDocsQuery("Values do not contain True or False"), ft.termsQuery(new ArrayList<>(), null)); + MappedFieldType doc_only_ft = new BooleanFieldMapper.BooleanFieldType("field", false, true); + + assertEquals( + SortedNumericDocValuesField.newSlowSetQuery("field", Stream.of(1).mapToLong(l -> l).toArray()), + doc_only_ft.termsQuery(newTerms, null) + ); MappedFieldType unsearchable = new BooleanFieldMapper.BooleanFieldType("field", false, false); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> unsearchable.termsQuery(terms, null));