-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[Star Tree] Support of Boolean Queries in Aggregations #17941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
641d617
Add bool filter provider
imRishN 23b6b87
Merge remote-tracking branch 'origin/main' into bool-star-tree
imRishN 525e2d2
should clause support
imRishN 9dbe1bf
Handle nested bool queries with merging
imRishN 1adb472
Remove test cases
imRishN 0d22537
Add should clause support
imRishN 308c3c9
Add tests
imRishN d766111
Add tests
imRishN ac34a73
Add test
imRishN 5a0ecf1
Add tests
imRishN ae76035
Tests for basic must clause
imRishN 4cb1f66
Add tests for basic should clause
imRishN c937541
Add tests
imRishN b508ea6
Add tests
imRishN 25e611e
Add tests
imRishN f883f32
Add tests
imRishN 04eb4c5
Add tests
imRishN 5d9fe8d
Clean up
imRishN a17d242
Handle must inside should
imRishN 6db89a5
Add tests for must inside should
imRishN a5adef0
Move BoolStarTreeFilterProvider to different source file
imRishN e4d43f9
Handle filter clause
imRishN 1496990
refactor
imRishN b82451f
Add keyword and float range tests
imRishN 8750aa4
Add float intersection test
imRishN 00175f9
Move comparator to DimensionFilterMapper
imRishN 04b55d0
Resolve conflicts
imRishN c38e5c6
Handle unsigned long
imRishN e35753b
Handle min should match
imRishN 761a2c5
Add Changelog
imRishN 67ea842
Fix spotless check
imRishN 80cc481
Revert ff change
imRishN 4ad0040
Add java doc
imRishN 02452fb
Rename merger class
imRishN a99a01c
Fix conflict
imRishN 65bf043
Fix spotless check
imRishN 2596863
Fix conflict
imRishN fa3382c
Refactor
imRishN 4cbf846
Add tests for null checks
imRishN 63b786d
Minor changes and add tests
imRishN File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
191 changes: 191 additions & 0 deletions
191
server/src/main/java/org/opensearch/search/startree/filter/DimensionFilterMergerUtils.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,191 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| package org.opensearch.search.startree.filter; | ||
|
|
||
| import org.opensearch.search.startree.filter.provider.DimensionFilterMapper; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| /** | ||
| * Utility class for merging different types of {@link DimensionFilter} | ||
| * Handles intersection operations between {@link ExactMatchDimFilter} and {@link RangeMatchDimFilter} | ||
| */ | ||
| public class DimensionFilterMergerUtils { | ||
|
Check warning on line 22 in server/src/main/java/org/opensearch/search/startree/filter/DimensionFilterMergerUtils.java
|
||
|
|
||
| /** | ||
| * Gets intersection of two DimensionFilters | ||
| * Returns null if intersection results in no possible matches. | ||
| */ | ||
| public static DimensionFilter intersect(DimensionFilter filter1, DimensionFilter filter2, DimensionFilterMapper mapper) { | ||
| if (filter1 == null || filter2 == null) { | ||
| return null; | ||
| } | ||
|
|
||
| if (filter1.getDimensionName() == null || filter2.getDimensionName() == null) { | ||
| throw new IllegalArgumentException("Cannot intersect filters with null dimension name"); | ||
| } | ||
|
|
||
| // Verify filters are for same dimension | ||
| if (!filter1.getDimensionName().equals(filter2.getDimensionName())) { | ||
| throw new IllegalArgumentException( | ||
| "Cannot intersect filters for different dimensions: " + filter1.getDimensionName() + " and " + filter2.getDimensionName() | ||
| ); | ||
| } | ||
|
|
||
| // Handle Range + Range combination | ||
| if (filter1 instanceof RangeMatchDimFilter && filter2 instanceof RangeMatchDimFilter) { | ||
| return intersectRangeFilters((RangeMatchDimFilter) filter1, (RangeMatchDimFilter) filter2, mapper); | ||
| } | ||
|
|
||
| // Handle ExactMatch + ExactMatch combination | ||
| if (filter1 instanceof ExactMatchDimFilter && filter2 instanceof ExactMatchDimFilter) { | ||
| return intersectExactMatchFilters((ExactMatchDimFilter) filter1, (ExactMatchDimFilter) filter2); | ||
| } | ||
|
|
||
| // Handle Range + ExactMatch combination | ||
| if (filter1 instanceof RangeMatchDimFilter && filter2 instanceof ExactMatchDimFilter) { | ||
| return intersectRangeWithExactMatch((RangeMatchDimFilter) filter1, (ExactMatchDimFilter) filter2, mapper); | ||
| } | ||
|
|
||
| // Handle ExactMatch + Range combination | ||
| if (filter1 instanceof ExactMatchDimFilter && filter2 instanceof RangeMatchDimFilter) { | ||
| return intersectRangeWithExactMatch((RangeMatchDimFilter) filter2, (ExactMatchDimFilter) filter1, mapper); | ||
| } | ||
|
|
||
| // throw exception for unsupported exception | ||
| throw new IllegalArgumentException( | ||
| "Unsupported filter combination: " + filter1.getClass().getSimpleName() + " and " + filter2.getClass().getSimpleName() | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Intersects two range filters | ||
| * Returns null if ranges don't overlap | ||
| */ | ||
| private static DimensionFilter intersectRangeFilters( | ||
| RangeMatchDimFilter range1, | ||
| RangeMatchDimFilter range2, | ||
| DimensionFilterMapper mapper | ||
| ) { | ||
| Object low1 = range1.getLow(); | ||
| Object high1 = range1.getHigh(); | ||
| Object low2 = range2.getLow(); | ||
| Object high2 = range2.getHigh(); | ||
|
|
||
| // Find the more restrictive bounds | ||
| Object newLow; | ||
| boolean includeLow; | ||
| if (low1 == null) { | ||
| newLow = low2; | ||
| includeLow = range2.isIncludeLow(); | ||
| } else if (low2 == null) { | ||
| newLow = low1; | ||
| includeLow = range1.isIncludeLow(); | ||
| } else { | ||
| int comparison = mapper.compareValues(low1, low2); | ||
| if (comparison > 0) { | ||
| newLow = low1; | ||
| includeLow = range1.isIncludeLow(); | ||
| } else if (comparison < 0) { | ||
| newLow = low2; | ||
| includeLow = range2.isIncludeLow(); | ||
| } else { | ||
| newLow = low1; | ||
| includeLow = range1.isIncludeLow() && range2.isIncludeLow(); | ||
| } | ||
| } | ||
|
|
||
| Object newHigh; | ||
| boolean includeHigh; | ||
| if (high1 == null) { | ||
| newHigh = high2; | ||
| includeHigh = range2.isIncludeHigh(); | ||
| } else if (high2 == null) { | ||
| newHigh = high1; | ||
| includeHigh = range1.isIncludeHigh(); | ||
| } else { | ||
| int comparison = mapper.compareValues(high1, high2); | ||
| if (comparison < 0) { | ||
| newHigh = high1; | ||
| includeHigh = range1.isIncludeHigh(); | ||
| } else if (comparison > 0) { | ||
| newHigh = high2; | ||
| includeHigh = range2.isIncludeHigh(); | ||
| } else { | ||
| newHigh = high1; | ||
| includeHigh = range1.isIncludeHigh() && range2.isIncludeHigh(); | ||
| } | ||
| } | ||
|
|
||
| // Check if range is valid | ||
| if (newLow != null && newHigh != null) { | ||
| if (!mapper.isValidRange(newLow, newHigh, includeLow, includeHigh)) { | ||
| return null; // No overlap | ||
| } | ||
| } | ||
|
|
||
| return new RangeMatchDimFilter(range1.getDimensionName(), newLow, newHigh, includeLow, includeHigh); | ||
| } | ||
|
|
||
| /** | ||
| * Intersects two exact match filters | ||
| * Returns null if no common values | ||
| */ | ||
| private static DimensionFilter intersectExactMatchFilters(ExactMatchDimFilter exact1, ExactMatchDimFilter exact2) { | ||
| List<Object> values1 = exact1.getRawValues(); | ||
| Set<Object> values2Set = new HashSet<>(exact2.getRawValues()); | ||
|
|
||
| List<Object> intersection = new ArrayList<>(); | ||
| for (Object value : values1) { | ||
| if (values2Set.contains(value)) { | ||
| intersection.add(value); | ||
| } | ||
| } | ||
|
|
||
| if (intersection.isEmpty()) { | ||
| return null; | ||
| } | ||
|
|
||
| return new ExactMatchDimFilter(exact1.getDimensionName(), intersection); | ||
| } | ||
|
|
||
| /** | ||
| * Intersects a range filter with an exact match filter. | ||
| * Returns null if no values from exact match are within range. | ||
| */ | ||
| private static DimensionFilter intersectRangeWithExactMatch( | ||
| RangeMatchDimFilter range, | ||
| ExactMatchDimFilter exact, | ||
| DimensionFilterMapper mapper | ||
| ) { | ||
| List<Object> validValues = new ArrayList<>(); | ||
|
|
||
| for (Object value : exact.getRawValues()) { | ||
| if (isValueInRange(value, range, mapper)) { | ||
| validValues.add(value); | ||
| } | ||
| } | ||
|
|
||
| if (validValues.isEmpty()) { | ||
| return null; | ||
| } | ||
|
|
||
| return new ExactMatchDimFilter(exact.getDimensionName(), validValues); | ||
| } | ||
|
|
||
| /** | ||
| * Checks if a value falls within a range. | ||
| */ | ||
| private static boolean isValueInRange(Object value, RangeMatchDimFilter range, DimensionFilterMapper mapper) { | ||
| return mapper.isValueInRange(value, range.getLow(), range.getHigh(), range.isIncludeLow(), range.isIncludeHigh()); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.