Skip to content

Commit f33c9bc

Browse files
authored
Merge branch 'main' into main
Signed-off-by: Tommy Shao <[email protected]>
2 parents 4a659c0 + e7e19f7 commit f33c9bc

File tree

13 files changed

+245
-12
lines changed

13 files changed

+245
-12
lines changed

.github/benchmark-configs.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,5 +256,21 @@
256256
"data_instance_config": "4vCPU, 32G Mem, 16G Heap"
257257
},
258258
"baseline_cluster_config": "x64-r5.xlarge-1-shard-0-replica-snapshot-baseline"
259+
},
260+
"id_16": {
261+
"description": "Benchmarking config for NESTED workload, benchmarks nested queries with inner-hits",
262+
"supported_major_versions": ["2", "3"],
263+
"cluster-benchmark-configs": {
264+
"SINGLE_NODE_CLUSTER": "true",
265+
"MIN_DISTRIBUTION": "true",
266+
"TEST_WORKLOAD": "nested",
267+
"WORKLOAD_PARAMS": "{\"number_of_replicas\":\"0\",\"number_of_shards\":\"1\"}",
268+
"CAPTURE_NODE_STAT": "true"
269+
},
270+
"cluster_configuration": {
271+
"size": "Single-Node",
272+
"data_instance_config": "4vCPU, 32G Mem, 16G Heap"
273+
},
274+
"baseline_cluster_config": "x64-r5.xlarge-single-node-1-shard-0-replica-baseline"
275+
}
259276
}
260-
}

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5959
- Bump `com.microsoft.azure:msal4j` from 1.17.2 to 1.18.0 ([#16918](https://github.com/opensearch-project/OpenSearch/pull/16918))
6060
- Bump `org.apache.commons:commons-text` from 1.12.0 to 1.13.0 ([#16919](https://github.com/opensearch-project/OpenSearch/pull/16919))
6161
- Bump `ch.qos.logback:logback-core` from 1.5.12 to 1.5.16 ([#16951](https://github.com/opensearch-project/OpenSearch/pull/16951))
62+
- Bump `com.azure:azure-core-http-netty` from 1.15.5 to 1.15.7 ([#16952](https://github.com/opensearch-project/OpenSearch/pull/16952))
6263

6364
### Changed
6465
- Indexed IP field supports `terms_query` with more than 1025 IP masks [#16391](https://github.com/opensearch-project/OpenSearch/pull/16391)
@@ -86,8 +87,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8687
- Skip remote-repositories validations for node-joins when RepositoriesService is not in sync with cluster-state ([#16763](https://github.com/opensearch-project/OpenSearch/pull/16763))
8788
- Fix _list/shards API failing when closed indices are present ([#16606](https://github.com/opensearch-project/OpenSearch/pull/16606))
8889
- Fix remote shards balance ([#15335](https://github.com/opensearch-project/OpenSearch/pull/15335))
89-
- Fixing the bug to prevent updating the index.knn setting during restore snapshot(#16957)[https://github.com/opensearch-project/OpenSearch/pull/16957]
90-
90+
- Always use `constant_score` query for `match_only_text` field ([#16964](https://github.com/opensearch-project/OpenSearch/pull/16964))
91+
- Fixing the bug to prevent updating the index.knn setting during restore snapshot ([#16957](https://github.com/opensearch-project/OpenSearch/pull/16957))
9192

9293
### Security
9394

plugins/repository-azure/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ dependencies {
4848
api 'com.azure:azure-json:1.3.0'
4949
api 'com.azure:azure-xml:1.1.0'
5050
api 'com.azure:azure-storage-common:12.28.0'
51-
api 'com.azure:azure-core-http-netty:1.15.5'
51+
api 'com.azure:azure-core-http-netty:1.15.7'
5252
api "io.netty:netty-codec-dns:${versions.netty}"
5353
api "io.netty:netty-codec-socks:${versions.netty}"
5454
api "io.netty:netty-codec-http2:${versions.netty}"

plugins/repository-azure/licenses/azure-core-http-netty-1.15.5.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a83247eeeb7f63f891e725228d54c3c24132c66a

server/src/main/java/org/opensearch/index/compositeindex/datacube/startree/utils/StarTreeQueryHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private static MetricStat validateStarTreeMetricSupport(
152152
MetricStat metricStat = ((MetricAggregatorFactory) aggregatorFactory).getMetricStat();
153153
field = ((MetricAggregatorFactory) aggregatorFactory).getField();
154154

155-
if (supportedMetrics.containsKey(field) && supportedMetrics.get(field).contains(metricStat)) {
155+
if (field != null && supportedMetrics.containsKey(field) && supportedMetrics.get(field).contains(metricStat)) {
156156
return metricStat;
157157
}
158158
}

server/src/main/java/org/opensearch/index/mapper/MatchOnlyTextFieldMapper.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.apache.lucene.index.Term;
1717
import org.apache.lucene.search.BooleanClause;
1818
import org.apache.lucene.search.BooleanQuery;
19+
import org.apache.lucene.search.ConstantScoreQuery;
1920
import org.apache.lucene.search.MultiPhraseQuery;
2021
import org.apache.lucene.search.PhraseQuery;
2122
import org.apache.lucene.search.Query;
@@ -290,6 +291,16 @@ public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions,
290291
return new SourceFieldMatchQuery(builder.build(), phrasePrefixQuery, this, context);
291292
}
292293

294+
@Override
295+
public Query termQuery(Object value, QueryShardContext context) {
296+
return new ConstantScoreQuery(super.termQuery(value, context));
297+
}
298+
299+
@Override
300+
public Query termQueryCaseInsensitive(Object value, QueryShardContext context) {
301+
return new ConstantScoreQuery(super.termQueryCaseInsensitive(value, context));
302+
}
303+
293304
private List<List<Term>> getTermsFromTokenStream(TokenStream stream) throws IOException {
294305
final List<List<Term>> termArray = new ArrayList<>();
295306
TermToBytesRefAttribute termAtt = stream.getAttribute(TermToBytesRefAttribute.class);

server/src/main/java/org/opensearch/search/aggregations/support/ValuesSourceAggregatorFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,6 @@ public String getStatsSubtype() {
104104
}
105105

106106
public String getField() {
107-
return config.fieldContext().field();
107+
return config.fieldContext() != null ? config.fieldContext().field() : null;
108108
}
109109
}

server/src/test/java/org/opensearch/index/mapper/MatchOnlyTextFieldMapperTests.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
import org.apache.lucene.index.Term;
1616
import org.apache.lucene.search.BooleanClause;
1717
import org.apache.lucene.search.BooleanQuery;
18+
import org.apache.lucene.search.ConstantScoreQuery;
1819
import org.apache.lucene.search.MultiPhraseQuery;
1920
import org.apache.lucene.search.PhraseQuery;
2021
import org.apache.lucene.search.Query;
2122
import org.apache.lucene.search.TermQuery;
2223
import org.apache.lucene.tests.analysis.MockSynonymAnalyzer;
24+
import org.opensearch.common.lucene.search.AutomatonQueries;
2325
import org.opensearch.common.lucene.search.MultiPhrasePrefixQuery;
2426
import org.opensearch.core.common.Strings;
2527
import org.opensearch.core.xcontent.MediaTypeRegistry;
@@ -28,6 +30,7 @@
2830
import org.opensearch.index.query.MatchPhraseQueryBuilder;
2931
import org.opensearch.index.query.QueryShardContext;
3032
import org.opensearch.index.query.SourceFieldMatchQuery;
33+
import org.opensearch.index.query.TermQueryBuilder;
3134
import org.opensearch.index.search.MatchQuery;
3235
import org.junit.Before;
3336

@@ -391,7 +394,7 @@ public void testPhraseQuery() throws IOException {
391394

392395
assertThat(q, is(expectedQuery));
393396
Query q4 = new MatchPhraseQueryBuilder("field", "singleton").toQuery(queryShardContext);
394-
assertThat(q4, is(new TermQuery(new Term("field", "singleton"))));
397+
assertThat(q4, is(new ConstantScoreQuery(new TermQuery(new Term("field", "singleton")))));
395398

396399
Query q2 = new MatchPhraseQueryBuilder("field", "three words here").toQuery(queryShardContext);
397400
expectedQuery = new SourceFieldMatchQuery(
@@ -447,4 +450,22 @@ public void testPhraseQuery() throws IOException {
447450
);
448451
assertThat(q6, is(expectedQuery));
449452
}
453+
454+
public void testTermQuery() throws Exception {
455+
MapperService mapperService = createMapperService(mapping(b -> {
456+
b.startObject("field");
457+
{
458+
b.field("type", textFieldName);
459+
b.field("analyzer", "my_stop_analyzer"); // "standard" will be replaced with MockSynonymAnalyzer
460+
}
461+
b.endObject();
462+
}));
463+
QueryShardContext queryShardContext = createQueryShardContext(mapperService);
464+
465+
Query q = new TermQueryBuilder("field", "foo").rewrite(queryShardContext).toQuery(queryShardContext);
466+
assertEquals(new ConstantScoreQuery(new TermQuery(new Term("field", "foo"))), q);
467+
468+
q = new TermQueryBuilder("field", "foo").caseInsensitive(true).rewrite(queryShardContext).toQuery(queryShardContext);
469+
assertEquals(new ConstantScoreQuery(AutomatonQueries.caseInsensitiveTermQuery(new Term("field", "foo"))), q);
470+
}
450471
}

server/src/test/java/org/opensearch/index/mapper/MatchOnlyTextFieldTypeTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88

99
package org.opensearch.index.mapper;
1010

11+
import org.apache.lucene.index.Term;
12+
import org.apache.lucene.search.ConstantScoreQuery;
13+
import org.apache.lucene.search.TermQuery;
1114
import org.opensearch.common.lucene.Lucene;
15+
import org.opensearch.common.lucene.search.AutomatonQueries;
1216

1317
public class MatchOnlyTextFieldTypeTests extends TextFieldTypeTests {
1418

@@ -28,4 +32,18 @@ TextFieldMapper.TextFieldType createFieldType(boolean searchable) {
2832
ParametrizedFieldMapper.Parameter.metaParam().get()
2933
);
3034
}
35+
36+
@Override
37+
public void testTermQuery() {
38+
MappedFieldType ft = createFieldType(true);
39+
assertEquals(new ConstantScoreQuery(new TermQuery(new Term("field", "foo"))), ft.termQuery("foo", null));
40+
assertEquals(
41+
new ConstantScoreQuery(AutomatonQueries.caseInsensitiveTermQuery(new Term("field", "fOo"))),
42+
ft.termQueryCaseInsensitive("fOo", null)
43+
);
44+
45+
MappedFieldType unsearchable = createFieldType(false);
46+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> unsearchable.termQuery("bar", null));
47+
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
48+
}
3149
}

server/src/test/java/org/opensearch/search/aggregations/startree/MetricAggregatorTests.java

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,27 @@
2828
import org.opensearch.common.lucene.Lucene;
2929
import org.opensearch.common.settings.Settings;
3030
import org.opensearch.common.util.FeatureFlags;
31+
import org.opensearch.common.util.MockBigArrays;
32+
import org.opensearch.common.util.MockPageCacheRecycler;
33+
import org.opensearch.core.indices.breaker.CircuitBreakerService;
34+
import org.opensearch.core.indices.breaker.NoneCircuitBreakerService;
3135
import org.opensearch.index.codec.composite.CompositeIndexFieldInfo;
3236
import org.opensearch.index.codec.composite.CompositeIndexReader;
3337
import org.opensearch.index.codec.composite.composite912.Composite912Codec;
3438
import org.opensearch.index.codec.composite912.datacube.startree.StarTreeDocValuesFormatTests;
3539
import org.opensearch.index.compositeindex.datacube.Dimension;
40+
import org.opensearch.index.compositeindex.datacube.Metric;
41+
import org.opensearch.index.compositeindex.datacube.MetricStat;
3642
import org.opensearch.index.compositeindex.datacube.NumericDimension;
3743
import org.opensearch.index.mapper.MappedFieldType;
3844
import org.opensearch.index.mapper.MapperService;
3945
import org.opensearch.index.mapper.NumberFieldMapper;
4046
import org.opensearch.index.query.QueryBuilder;
47+
import org.opensearch.index.query.QueryShardContext;
4148
import org.opensearch.index.query.TermQueryBuilder;
4249
import org.opensearch.search.aggregations.AggregationBuilder;
50+
import org.opensearch.search.aggregations.AggregatorFactories;
51+
import org.opensearch.search.aggregations.AggregatorFactory;
4352
import org.opensearch.search.aggregations.AggregatorTestCase;
4453
import org.opensearch.search.aggregations.InternalAggregation;
4554
import org.opensearch.search.aggregations.metrics.AvgAggregationBuilder;
@@ -49,14 +58,17 @@
4958
import org.opensearch.search.aggregations.metrics.InternalSum;
5059
import org.opensearch.search.aggregations.metrics.InternalValueCount;
5160
import org.opensearch.search.aggregations.metrics.MaxAggregationBuilder;
61+
import org.opensearch.search.aggregations.metrics.MetricAggregatorFactory;
5262
import org.opensearch.search.aggregations.metrics.MinAggregationBuilder;
5363
import org.opensearch.search.aggregations.metrics.SumAggregationBuilder;
5464
import org.opensearch.search.aggregations.metrics.ValueCountAggregationBuilder;
65+
import org.opensearch.search.aggregations.support.ValuesSourceAggregatorFactory;
5566
import org.junit.After;
5667
import org.junit.Before;
5768

5869
import java.io.IOException;
5970
import java.util.ArrayList;
71+
import java.util.Collections;
6072
import java.util.LinkedList;
6173
import java.util.List;
6274
import java.util.Random;
@@ -69,6 +81,8 @@
6981
import static org.opensearch.search.aggregations.AggregationBuilders.min;
7082
import static org.opensearch.search.aggregations.AggregationBuilders.sum;
7183
import static org.opensearch.test.InternalAggregationTestCase.DEFAULT_MAX_BUCKETS;
84+
import static org.mockito.Mockito.mock;
85+
import static org.mockito.Mockito.when;
7286

7387
public class MetricAggregatorTests extends AggregatorTestCase {
7488

@@ -267,6 +281,110 @@ public void testStarTreeDocValues() throws IOException {
267281
);
268282
}
269283

284+
CircuitBreakerService circuitBreakerService = new NoneCircuitBreakerService();
285+
286+
QueryShardContext queryShardContext = queryShardContextMock(
287+
indexSearcher,
288+
mapperServiceMock(),
289+
createIndexSettings(),
290+
circuitBreakerService,
291+
new MockBigArrays(new MockPageCacheRecycler(Settings.EMPTY), circuitBreakerService).withCircuitBreaking()
292+
);
293+
294+
MetricAggregatorFactory aggregatorFactory = mock(MetricAggregatorFactory.class);
295+
when(aggregatorFactory.getSubFactories()).thenReturn(AggregatorFactories.EMPTY);
296+
when(aggregatorFactory.getField()).thenReturn(FIELD_NAME);
297+
when(aggregatorFactory.getMetricStat()).thenReturn(MetricStat.SUM);
298+
299+
// Case when field and metric type in aggregation are fully supported by star tree.
300+
testCase(
301+
indexSearcher,
302+
query,
303+
queryBuilder,
304+
sumAggregationBuilder,
305+
starTree,
306+
supportedDimensions,
307+
List.of(new Metric(FIELD_NAME, List.of(MetricStat.SUM, MetricStat.MAX, MetricStat.MIN, MetricStat.AVG))),
308+
verifyAggregation(InternalSum::getValue),
309+
aggregatorFactory,
310+
true
311+
);
312+
313+
// Case when the field is not supported by star tree
314+
SumAggregationBuilder invalidFieldSumAggBuilder = sum("_name").field("hello");
315+
testCase(
316+
indexSearcher,
317+
query,
318+
queryBuilder,
319+
invalidFieldSumAggBuilder,
320+
starTree,
321+
supportedDimensions,
322+
Collections.emptyList(),
323+
verifyAggregation(InternalSum::getValue),
324+
invalidFieldSumAggBuilder.build(queryShardContext, null),
325+
false // Invalid fields will return null StarTreeQueryContext which will not cause early termination by leaf collector
326+
);
327+
328+
// Case when metric type in aggregation is not supported by star tree but the field is supported.
329+
testCase(
330+
indexSearcher,
331+
query,
332+
queryBuilder,
333+
sumAggregationBuilder,
334+
starTree,
335+
supportedDimensions,
336+
List.of(new Metric(FIELD_NAME, List.of(MetricStat.MAX, MetricStat.MIN, MetricStat.AVG))),
337+
verifyAggregation(InternalSum::getValue),
338+
aggregatorFactory,
339+
false
340+
);
341+
342+
// Case when field is not present in supported metrics
343+
testCase(
344+
indexSearcher,
345+
query,
346+
queryBuilder,
347+
sumAggregationBuilder,
348+
starTree,
349+
supportedDimensions,
350+
List.of(new Metric("hello", List.of(MetricStat.MAX, MetricStat.MIN, MetricStat.AVG))),
351+
verifyAggregation(InternalSum::getValue),
352+
aggregatorFactory,
353+
false
354+
);
355+
356+
AggregatorFactories aggregatorFactories = mock(AggregatorFactories.class);
357+
when(aggregatorFactories.getFactories()).thenReturn(new AggregatorFactory[] { mock(MetricAggregatorFactory.class) });
358+
when(aggregatorFactory.getSubFactories()).thenReturn(aggregatorFactories);
359+
360+
// Case when sub aggregations are present
361+
testCase(
362+
indexSearcher,
363+
query,
364+
queryBuilder,
365+
sumAggregationBuilder,
366+
starTree,
367+
supportedDimensions,
368+
List.of(new Metric("hello", List.of(MetricStat.MAX, MetricStat.MIN, MetricStat.AVG))),
369+
verifyAggregation(InternalSum::getValue),
370+
aggregatorFactory,
371+
false
372+
);
373+
374+
// Case when aggregation factory is not metric aggregation
375+
testCase(
376+
indexSearcher,
377+
query,
378+
queryBuilder,
379+
sumAggregationBuilder,
380+
starTree,
381+
supportedDimensions,
382+
List.of(new Metric("hello", List.of(MetricStat.MAX, MetricStat.MIN, MetricStat.AVG))),
383+
verifyAggregation(InternalSum::getValue),
384+
mock(ValuesSourceAggregatorFactory.class),
385+
false
386+
);
387+
270388
ir.close();
271389
directory.close();
272390
}
@@ -287,6 +405,21 @@ private <T extends AggregationBuilder, V extends InternalAggregation> void testC
287405
CompositeIndexFieldInfo starTree,
288406
List<Dimension> supportedDimensions,
289407
BiConsumer<V, V> verify
408+
) throws IOException {
409+
testCase(searcher, query, queryBuilder, aggBuilder, starTree, supportedDimensions, Collections.emptyList(), verify, null, true);
410+
}
411+
412+
private <T extends AggregationBuilder, V extends InternalAggregation> void testCase(
413+
IndexSearcher searcher,
414+
Query query,
415+
QueryBuilder queryBuilder,
416+
T aggBuilder,
417+
CompositeIndexFieldInfo starTree,
418+
List<Dimension> supportedDimensions,
419+
List<Metric> supportedMetrics,
420+
BiConsumer<V, V> verify,
421+
AggregatorFactory aggregatorFactory,
422+
boolean assertCollectorEarlyTermination
290423
) throws IOException {
291424
V starTreeAggregation = searchAndReduceStarTree(
292425
createIndexSettings(),
@@ -296,8 +429,11 @@ private <T extends AggregationBuilder, V extends InternalAggregation> void testC
296429
aggBuilder,
297430
starTree,
298431
supportedDimensions,
432+
supportedMetrics,
299433
DEFAULT_MAX_BUCKETS,
300434
false,
435+
aggregatorFactory,
436+
assertCollectorEarlyTermination,
301437
DEFAULT_MAPPED_FIELD
302438
);
303439
V expectedAggregation = searchAndReduceStarTree(
@@ -308,8 +444,11 @@ private <T extends AggregationBuilder, V extends InternalAggregation> void testC
308444
aggBuilder,
309445
null,
310446
null,
447+
null,
311448
DEFAULT_MAX_BUCKETS,
312449
false,
450+
aggregatorFactory,
451+
assertCollectorEarlyTermination,
313452
DEFAULT_MAPPED_FIELD
314453
);
315454
verify.accept(expectedAggregation, starTreeAggregation);

0 commit comments

Comments
 (0)