-
Notifications
You must be signed in to change notification settings - Fork 0
Add Support for Nested Function Use In WHERE
Clause
#267
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,17 +8,20 @@ | |
|
||
import static java.util.stream.Collectors.mapping; | ||
import static java.util.stream.Collectors.toList; | ||
import static org.opensearch.index.query.QueryBuilders.boolQuery; | ||
import static org.opensearch.index.query.QueryBuilders.matchAllQuery; | ||
import static org.opensearch.index.query.QueryBuilders.nestedQuery; | ||
import static org.opensearch.search.sort.FieldSortBuilder.DOC_FIELD_NAME; | ||
import static org.opensearch.search.sort.SortOrder.ASC; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
@@ -44,7 +47,6 @@ | |
import org.opensearch.sql.opensearch.data.type.OpenSearchDataType; | ||
import org.opensearch.sql.opensearch.data.value.OpenSearchExprValueFactory; | ||
import org.opensearch.sql.opensearch.response.agg.OpenSearchAggregationResponseParser; | ||
import org.opensearch.sql.planner.logical.LogicalNested; | ||
|
||
/** | ||
* OpenSearch search request builder. | ||
|
@@ -257,13 +259,33 @@ private boolean isSortByDocOnly() { | |
*/ | ||
public void pushDownNested(List<Map<String, ReferenceExpression>> nestedArgs) { | ||
initBoolQueryFilter(); | ||
List<NestedQueryBuilder> nestedQueries = extractNestedQueries(query()); | ||
groupFieldNamesByPath(nestedArgs).forEach( | ||
(path, fieldNames) -> buildInnerHit( | ||
fieldNames, createEmptyNestedQuery(path) | ||
) | ||
(path, fieldNames) -> | ||
buildInnerHit(fieldNames, findNestedQueryWithSamePath(nestedQueries, path)) | ||
); | ||
} | ||
|
||
/** | ||
* InnerHit must be added to the NestedQueryBuilder. We need to extract | ||
* the nested queries currently in the query if there is already a filter | ||
* push down with nested query. | ||
* @param query : current query. | ||
* @return : grouped nested queries currently in query. | ||
*/ | ||
private List<NestedQueryBuilder> extractNestedQueries(QueryBuilder query) { | ||
List<NestedQueryBuilder> result = new ArrayList<>(); | ||
if (query instanceof NestedQueryBuilder) { | ||
result.add((NestedQueryBuilder) query); | ||
} else if (query instanceof BoolQueryBuilder) { | ||
BoolQueryBuilder boolQ = (BoolQueryBuilder) query; | ||
Stream.of(boolQ.filter(), boolQ.must(), boolQ.should()) | ||
.flatMap(Collection::stream) | ||
.forEach(q -> result.addAll(extractNestedQueries(q))); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* Initialize bool query for push down. | ||
*/ | ||
|
@@ -307,13 +329,41 @@ private void buildInnerHit(List<String> paths, NestedQueryBuilder query) { | |
)); | ||
} | ||
|
||
/** | ||
* We need to group nested queries with same path for adding new fields with same path of | ||
* inner hits. If we try to add additional inner hits with same path we get an OS error. | ||
* @param nestedQueries Current list of nested queries in query. | ||
* @param path path comparing with current nested queries. | ||
* @return Query with same path or new empty nested query. | ||
*/ | ||
private NestedQueryBuilder findNestedQueryWithSamePath( | ||
List<NestedQueryBuilder> nestedQueries, String path | ||
) { | ||
return nestedQueries.stream() | ||
.filter(query -> isSamePath(path, query)) | ||
.findAny() | ||
.orElseGet(createEmptyNestedQuery(path)); | ||
} | ||
|
||
/** | ||
* Check if is nested query is of the same path value. | ||
* @param path Value of path to compare with nested query. | ||
* @param query nested query builder to compare with path. | ||
* @return true if nested query has same path. | ||
*/ | ||
private boolean isSamePath(String path, NestedQueryBuilder query) { | ||
return nestedQuery(path, query.query(), query.scoreMode()).equals(query); | ||
} | ||
|
||
/** | ||
* Create a nested query with match all filter to place inner hits. | ||
*/ | ||
private NestedQueryBuilder createEmptyNestedQuery(String path) { | ||
NestedQueryBuilder nestedQuery = nestedQuery(path, matchAllQuery(), ScoreMode.None); | ||
((BoolQueryBuilder) query().filter().get(0)).must(nestedQuery); | ||
return nestedQuery; | ||
private Supplier<NestedQueryBuilder> createEmptyNestedQuery(String path) { | ||
return () -> { | ||
NestedQueryBuilder nestedQuery = nestedQuery(path, matchAllQuery(), ScoreMode.None); | ||
((BoolQueryBuilder) query().filter().get(0)).must(nestedQuery); | ||
return nestedQuery; | ||
Comment on lines
+361
to
+365
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this lambda function do? How is it different from a without the lambda function around it such as:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. The You can read more about this here: |
||
}; | ||
} | ||
|
||
/** | ||
|
Uh oh!
There was an error while loading. Please reload this page.