Skip to content

Commit 7d0a0bf

Browse files
authored
Merge branch 'main' into bhumika/fs-health-failure-metric
Signed-off-by: Bukhtawar Khan <[email protected]>
2 parents 4beaeb6 + 528e2b0 commit 7d0a0bf

26 files changed

+1432
-425
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
4242
- Added File Cache Pinning ([#17617](https://github.com/opensearch-project/OpenSearch/issues/13648))
4343
- Support consumer reset in Resume API for pull-based ingestion. This PR includes a breaking change for the experimental pull-based ingestion feature. ([#18332](https://github.com/opensearch-project/OpenSearch/pull/18332))
4444
- Add FIPS build tooling ([#4254](https://github.com/opensearch-project/security/issues/4254))
45+
- [Star-Tree] Support for date-range queries with star-tree supported aggregations ([#17855](https://github.com/opensearch-project/OpenSearch/pull/17855)
4546
- Added FS Health Check Failure metric ([#18435](https://github.com/opensearch-project/OpenSearch/pull/18435))
4647

4748
### Changed

server/src/main/java/org/opensearch/index/query/RangeQueryBuilder.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.lucene.search.MatchNoDocsQuery;
3636
import org.apache.lucene.search.Query;
3737
import org.apache.lucene.util.BytesRef;
38+
import org.opensearch.common.annotation.PublicApi;
3839
import org.opensearch.common.geo.ShapeRelation;
3940
import org.opensearch.common.time.DateFormatter;
4041
import org.opensearch.common.time.DateMathParser;
@@ -56,10 +57,12 @@
5657
import java.util.Objects;
5758

5859
/**
59-
* A Query that matches documents within an range of terms.
60+
* A Query that matches documents within a range of terms.
6061
*
6162
* @opensearch.internal
6263
*/
64+
// TODO: Revert @PublicApi annotation after @ExperimentalApi is removed from DimensionFilterMapper
65+
@PublicApi(since = "1.0.0")
6366
public class RangeQueryBuilder extends AbstractQueryBuilder<RangeQueryBuilder> implements MultiTermQueryBuilder {
6467
public static final String NAME = "range";
6568

server/src/main/java/org/opensearch/search/aggregations/bucket/histogram/DateHistogramAggregator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
import org.opensearch.search.internal.SearchContext;
6767
import org.opensearch.search.startree.StarTreeQueryHelper;
6868
import org.opensearch.search.startree.StarTreeTraversalUtil;
69-
import org.opensearch.search.startree.filter.DimensionFilter;
69+
import org.opensearch.search.startree.filter.MatchAllFilter;
7070

7171
import java.io.IOException;
7272
import java.util.Collections;
@@ -301,8 +301,8 @@ public StarTreeBucketCollector getStarTreeBucketCollector(
301301
starTreeValues,
302302
StarTreeQueryHelper.mergeDimensionFilterIfNotExists(
303303
context.getQueryShardContext().getStarTreeQueryContext().getBaseQueryStarTreeFilter(),
304-
starTreeDateDimension,
305-
List.of(DimensionFilter.MATCH_ALL_DEFAULT)
304+
fieldName,
305+
List.of(new MatchAllFilter(fieldName, starTreeDateDimension))
306306
),
307307
context
308308
)

server/src/main/java/org/opensearch/search/aggregations/bucket/range/RangeAggregator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
import org.opensearch.search.internal.SearchContext;
7272
import org.opensearch.search.startree.StarTreeQueryHelper;
7373
import org.opensearch.search.startree.StarTreeTraversalUtil;
74-
import org.opensearch.search.startree.filter.DimensionFilter;
74+
import org.opensearch.search.startree.filter.MatchAllFilter;
7575

7676
import java.io.IOException;
7777
import java.util.ArrayList;
@@ -396,7 +396,7 @@ public StarTreeBucketCollector getStarTreeBucketCollector(
396396
StarTreeQueryHelper.mergeDimensionFilterIfNotExists(
397397
context.getQueryShardContext().getStarTreeQueryContext().getBaseQueryStarTreeFilter(),
398398
fieldName,
399-
List.of(DimensionFilter.MATCH_ALL_DEFAULT)
399+
List.of(new MatchAllFilter(fieldName))
400400
),
401401
context
402402
)

server/src/main/java/org/opensearch/search/aggregations/bucket/terms/GlobalOrdinalsStringTermsAggregator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
import org.opensearch.search.internal.SearchContext;
7777
import org.opensearch.search.startree.StarTreeQueryHelper;
7878
import org.opensearch.search.startree.StarTreeTraversalUtil;
79-
import org.opensearch.search.startree.filter.DimensionFilter;
79+
import org.opensearch.search.startree.filter.MatchAllFilter;
8080

8181
import java.io.IOException;
8282
import java.util.Arrays;
@@ -343,7 +343,7 @@ public StarTreeBucketCollector getStarTreeBucketCollector(
343343
StarTreeQueryHelper.mergeDimensionFilterIfNotExists(
344344
context.getQueryShardContext().getStarTreeQueryContext().getBaseQueryStarTreeFilter(),
345345
fieldName,
346-
List.of(DimensionFilter.MATCH_ALL_DEFAULT)
346+
List.of(new MatchAllFilter(fieldName))
347347
),
348348
context
349349
)

server/src/main/java/org/opensearch/search/aggregations/bucket/terms/NumericTermsAggregator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
import org.opensearch.search.internal.SearchContext;
6969
import org.opensearch.search.startree.StarTreeQueryHelper;
7070
import org.opensearch.search.startree.StarTreeTraversalUtil;
71-
import org.opensearch.search.startree.filter.DimensionFilter;
71+
import org.opensearch.search.startree.filter.MatchAllFilter;
7272

7373
import java.io.IOException;
7474
import java.math.BigInteger;
@@ -187,7 +187,7 @@ public StarTreeBucketCollector getStarTreeBucketCollector(
187187
StarTreeQueryHelper.mergeDimensionFilterIfNotExists(
188188
context.getQueryShardContext().getStarTreeQueryContext().getBaseQueryStarTreeFilter(),
189189
fieldName,
190-
List.of(DimensionFilter.MATCH_ALL_DEFAULT)
190+
List.of(new MatchAllFilter(fieldName))
191191
),
192192
context
193193
)

server/src/main/java/org/opensearch/search/startree/StarTreeTraversalUtil.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@ public static FixedBitSet getStarTreeResult(StarTreeValues starTreeValues, StarT
8484
for (String remainingPredicateColumn : starTreeResult.remainingPredicateColumns) {
8585
logger.debug("remainingPredicateColumn : {}, maxMatchedDoc : {} ", remainingPredicateColumn, starTreeResult.maxMatchedDoc);
8686

87-
StarTreeValuesIterator valuesIterator = starTreeValues.getDimensionValuesIterator(remainingPredicateColumn);
8887
// Get the query value directly
8988
List<DimensionFilter> dimensionFilters = starTreeFilter.getFiltersForDimension(remainingPredicateColumn);
89+
StarTreeValuesIterator valuesIterator = starTreeValues.getDimensionValuesIterator(
90+
dimensionFilters.getFirst().getMatchingDimension()
91+
);
9092

9193
// Clear the temporary bit set before reuse
9294
tempBitSet.clear(0, starTreeResult.maxMatchedDoc + 1);
@@ -131,7 +133,7 @@ private static StarTreeResult traverseStarTree(StarTreeValues starTreeValues, St
131133
Queue<StarTreeNode> queue = new ArrayDeque<>();
132134
queue.add(starTree);
133135
int currentDimensionId = -1;
134-
Set<String> remainingPredicateColumns = new HashSet<>(starTreeFilter.getDimensions());
136+
Set<String> remainingPredicateColumns = new HashSet<>(starTreeFilter.getMatchingDimensions());
135137
int matchedDocsCountInStarTree = 0;
136138
int maxDocNum = -1;
137139
StarTreeNode starTreeNode;

server/src/main/java/org/opensearch/search/startree/filter/DimensionFilter.java

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,16 @@
1111
import org.opensearch.common.annotation.ExperimentalApi;
1212
import org.opensearch.index.compositeindex.datacube.startree.index.StarTreeValues;
1313
import org.opensearch.index.compositeindex.datacube.startree.node.StarTreeNode;
14-
import org.opensearch.index.compositeindex.datacube.startree.node.StarTreeNodeType;
1514
import org.opensearch.search.internal.SearchContext;
1615
import org.opensearch.search.startree.StarTreeNodeCollector;
1716

1817
import java.io.IOException;
19-
import java.util.Iterator;
2018

2119
/**
2220
* Contains the logic to filter over a dimension either in StarTree Index or it's Dimension DocValues
2321
*/
2422
@ExperimentalApi
2523
public interface DimensionFilter {
26-
27-
DimensionFilter MATCH_ALL_DEFAULT = new DimensionFilter() {
28-
@Override
29-
public void initialiseForSegment(StarTreeValues starTreeValues, SearchContext searchContext) throws IOException {
30-
31-
}
32-
33-
@Override
34-
public void matchStarTreeNodes(StarTreeNode parentNode, StarTreeValues starTreeValues, StarTreeNodeCollector collector)
35-
throws IOException {
36-
if (parentNode != null) {
37-
for (Iterator<? extends StarTreeNode> it = parentNode.getChildrenIterator(); it.hasNext();) {
38-
StarTreeNode starTreeNode = it.next();
39-
if (starTreeNode.getStarTreeNodeType() == StarTreeNodeType.DEFAULT.getValue()) {
40-
collector.collectStarTreeNode(starTreeNode);
41-
}
42-
}
43-
}
44-
}
45-
46-
@Override
47-
public boolean matchDimValue(long ordinal, StarTreeValues starTreeValues) {
48-
return true;
49-
}
50-
};
51-
5224
/**
5325
* Converts parsed user values to ordinals based on segment and other init actions can be performed.
5426
* @param starTreeValues : Segment specific star tree root node and other metadata
@@ -74,10 +46,16 @@ public boolean matchDimValue(long ordinal, StarTreeValues starTreeValues) {
7446
*/
7547
boolean matchDimValue(long ordinal, StarTreeValues starTreeValues);
7648

77-
default String getDimensionName() {
49+
String getDimensionName();
50+
51+
default String getSubDimensionName() {
7852
return null;
7953
}
8054

55+
default String getMatchingDimension() {
56+
return getSubDimensionName() == null ? getDimensionName() : getSubDimensionName();
57+
}
58+
8159
/**
8260
* Represents how to match a value when comparing during StarTreeTraversal
8361
*/
@@ -89,5 +67,4 @@ enum MatchType {
8967
LTE,
9068
EXACT
9169
}
92-
9370
}

server/src/main/java/org/opensearch/search/startree/filter/DimensionFilterMergerUtils.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,16 @@ private static DimensionFilter intersectRangeFilters(
133133
}
134134
}
135135

136-
return new RangeMatchDimFilter(range1.getDimensionName(), newLow, newHigh, includeLow, includeHigh);
136+
String effectiveSubDimension = mapper.resolveUsingSubDimension()
137+
? mapper.getSubDimensionFieldEffective(range1.getSubDimensionName(), range2.getSubDimensionName())
138+
: null;
139+
140+
return new RangeMatchDimFilter(range1.getDimensionName(), newLow, newHigh, includeLow, includeHigh) {
141+
@Override
142+
public String getSubDimensionName() {
143+
return effectiveSubDimension;
144+
}
145+
};
137146
}
138147

139148
/**

server/src/main/java/org/opensearch/search/startree/filter/ExactMatchDimFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public void initialiseForSegment(StarTreeValues starTreeValues, SearchContext se
5050
starTreeValues.getStarTreeField().getDimensionsOrder()
5151
);
5252
this.dimensionFilterMapper = DimensionFilterMapper.Factory.fromMappedFieldType(
53-
searchContext.mapperService().fieldType(dimensionName)
53+
searchContext.mapperService().fieldType(dimensionName),
54+
searchContext
5455
);
5556

5657
for (Object rawValue : rawValues) {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.search.startree.filter;
10+
11+
import org.opensearch.common.annotation.ExperimentalApi;
12+
import org.opensearch.index.compositeindex.datacube.startree.index.StarTreeValues;
13+
import org.opensearch.index.compositeindex.datacube.startree.node.StarTreeNode;
14+
import org.opensearch.index.compositeindex.datacube.startree.node.StarTreeNodeType;
15+
import org.opensearch.search.internal.SearchContext;
16+
import org.opensearch.search.startree.StarTreeNodeCollector;
17+
18+
import java.io.IOException;
19+
import java.util.Iterator;
20+
21+
/**
22+
* Matches all StarTreeNodes
23+
*/
24+
@ExperimentalApi
25+
public class MatchAllFilter implements DimensionFilter {
26+
27+
public final String dimensionName;
28+
public final String subDimensionName;
29+
30+
public MatchAllFilter(String dimensionName) {
31+
this.dimensionName = dimensionName;
32+
this.subDimensionName = null;
33+
}
34+
35+
public MatchAllFilter(String dimensionName, String subDimensionName) {
36+
this.dimensionName = dimensionName;
37+
this.subDimensionName = subDimensionName;
38+
}
39+
40+
@Override
41+
public void initialiseForSegment(StarTreeValues starTreeValues, SearchContext searchContext) throws IOException {}
42+
43+
@Override
44+
public void matchStarTreeNodes(StarTreeNode parentNode, StarTreeValues starTreeValues, StarTreeNodeCollector collector)
45+
throws IOException {
46+
if (parentNode != null) {
47+
for (Iterator<? extends StarTreeNode> it = parentNode.getChildrenIterator(); it.hasNext();) {
48+
StarTreeNode starTreeNode = it.next();
49+
if (starTreeNode.getStarTreeNodeType() == StarTreeNodeType.DEFAULT.getValue()) {
50+
collector.collectStarTreeNode(starTreeNode);
51+
}
52+
}
53+
}
54+
}
55+
56+
@Override
57+
public boolean matchDimValue(long ordinal, StarTreeValues starTreeValues) {
58+
return true;
59+
}
60+
61+
@Override
62+
public String getDimensionName() {
63+
return dimensionName;
64+
}
65+
66+
public String getSubDimensionName() {
67+
return subDimensionName;
68+
}
69+
70+
}

server/src/main/java/org/opensearch/search/startree/filter/MatchNoneFilter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ public void matchStarTreeNodes(StarTreeNode parentNode, StarTreeValues starTreeV
3434
public boolean matchDimValue(long ordinal, StarTreeValues starTreeValues) {
3535
return false;
3636
}
37+
38+
@Override
39+
public String getDimensionName() {
40+
return null;
41+
}
3742
}

server/src/main/java/org/opensearch/search/startree/filter/RangeMatchDimFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public RangeMatchDimFilter(String dimensionName, Object low, Object high, boolea
5151
public void initialiseForSegment(StarTreeValues starTreeValues, SearchContext searchContext) {
5252
skipRangeCollection = false;
5353
this.dimensionFilterMapper = DimensionFilterMapper.Factory.fromMappedFieldType(
54-
searchContext.mapperService().fieldType(dimensionName)
54+
searchContext.mapperService().fieldType(dimensionName),
55+
searchContext
5556
);
5657

5758
lowOrdinal = 0L;

server/src/main/java/org/opensearch/search/startree/filter/StarTreeFilter.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.opensearch.common.annotation.ExperimentalApi;
1212

13+
import java.util.HashSet;
1314
import java.util.List;
1415
import java.util.Map;
1516
import java.util.Set;
@@ -23,16 +24,38 @@ public class StarTreeFilter {
2324
private final Map<String, List<DimensionFilter>> dimensionFilterMap;
2425

2526
public StarTreeFilter(Map<String, List<DimensionFilter>> dimensionFilterMap) {
27+
// TODO: Evaluate wrapping of List<DimensionFilter> to expose a single effective sub-dimension field
28+
// https://github.com/opensearch-project/OpenSearch/issues/18477
2629
this.dimensionFilterMap = dimensionFilterMap;
2730
}
2831

2932
public List<DimensionFilter> getFiltersForDimension(String dimension) {
30-
return dimensionFilterMap.get(dimension);
33+
// TODO: Refactor with https://github.com/opensearch-project/OpenSearch/issues/18477
34+
return dimensionFilterMap.containsKey(dimension)
35+
? dimensionFilterMap.get(dimension)
36+
: dimensionFilterMap.values()
37+
.stream()
38+
.filter(filters -> filters != null && !filters.isEmpty() && dimension.equals(filters.getFirst().getMatchingDimension()))
39+
.findFirst()
40+
.orElse(null);
3141
}
3242

3343
public Set<String> getDimensions() {
3444
return dimensionFilterMap.keySet();
3545
}
46+
47+
public Set<String> getMatchingDimensions() {
48+
// TODO: Refactor with: https://github.com/opensearch-project/OpenSearch/issues/18477
49+
Set<String> matchingDimensions = new HashSet<>();
50+
for (Map.Entry<String, List<DimensionFilter>> entry : dimensionFilterMap.entrySet()) {
51+
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
52+
String matchingDimension = entry.getValue().getFirst().getMatchingDimension();
53+
// Anonymous implementations of DimensionFilter may not have dimension info
54+
matchingDimensions.add(matchingDimension == null ? entry.getKey() : matchingDimension);
55+
}
56+
}
57+
return matchingDimensions;
58+
}
3659
// TODO : Implement Merging of 2 Star Tree Filters
3760
// This would also involve merging 2 different types of dimension filters.
3861
// It also brings in the challenge of sorting input values in user query for efficient merging.

0 commit comments

Comments
 (0)