Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Add sub aggregation support for histogram aggregation using skiplist ([19438](https://github.com/opensearch-project/OpenSearch/pull/19438))
- Optimization in String Terms Aggregation query for Large Bucket Counts([#18732](https://github.com/opensearch-project/OpenSearch/pull/18732))
- New cluster setting search.query.max_query_string_length ([#19491](https://github.com/opensearch-project/OpenSearch/pull/19491))
- Implement GRPC Highlight, Sort search params ([#19500](https://github.com/opensearch-project/OpenSearch/pull/19500))

### Changed
- Refactor `if-else` chains to use `Java 17 pattern matching switch expressions`(([#18965](https://github.com/opensearch-project/OpenSearch/pull/18965))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class BulkRequestParserProtoUtils {
/**
* Private constructor to prevent instantiation of utility class.
*/
protected BulkRequestParserProtoUtils() {
private BulkRequestParserProtoUtils() {
// Utility class, no instances
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.opensearch.index.query.InnerHitBuilder;
import org.opensearch.protobufs.FieldCollapse;
import org.opensearch.search.collapse.CollapseBuilder;
import org.opensearch.transport.grpc.spi.QueryBuilderProtoConverterRegistry;

import java.io.IOException;
import java.util.ArrayList;
Expand All @@ -36,10 +37,12 @@ private CollapseBuilderProtoUtils() {
* and inner hits settings.
*
* @param collapseProto The Protocol Buffer FieldCollapse to convert
* @param registry The registry for query conversion (needed for inner hits with sorts/highlights)
* @return A configured CollapseBuilder instance
* @throws IOException if there's an error during parsing or conversion
*/
protected static CollapseBuilder fromProto(FieldCollapse collapseProto) throws IOException {
protected static CollapseBuilder fromProto(FieldCollapse collapseProto, QueryBuilderProtoConverterRegistry registry)
throws IOException {
CollapseBuilder collapseBuilder = new CollapseBuilder(collapseProto.getField());

if (collapseProto.hasMaxConcurrentGroupSearches()) {
Expand All @@ -48,7 +51,7 @@ protected static CollapseBuilder fromProto(FieldCollapse collapseProto) throws I
if (collapseProto.getInnerHitsCount() > 0) {
List<InnerHitBuilder> innerHitBuilders = new ArrayList<>();
for (org.opensearch.protobufs.InnerHits innerHits : collapseProto.getInnerHitsList()) {
innerHitBuilders.add(InnerHitsBuilderProtoUtils.fromProto(innerHits));
innerHitBuilders.add(InnerHitsBuilderProtoUtils.fromProto(innerHits, registry));
}
collapseBuilder.setInnerHits(innerHitBuilders);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@
package org.opensearch.transport.grpc.proto.request.search;

import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.index.query.QueryBuilder;
import org.opensearch.protobufs.BoundaryScanner;
import org.opensearch.protobufs.BuiltinHighlighterType;
import org.opensearch.protobufs.Highlight;
import org.opensearch.protobufs.HighlighterEncoder;
import org.opensearch.protobufs.HighlighterFragmenter;
import org.opensearch.protobufs.HighlighterOrder;
import org.opensearch.protobufs.HighlighterTagsSchema;
import org.opensearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.opensearch.transport.grpc.proto.request.common.ObjectMapProtoUtils;
import org.opensearch.transport.grpc.spi.QueryBuilderProtoConverterRegistry;
import org.opensearch.transport.grpc.util.ProtobufEnumUtils;

/**
* Utility class for converting Highlight Protocol Buffers to OpenSearch objects.
* This class provides methods to transform Protocol Buffer representations of highlights
* into their corresponding OpenSearch HighlightBuilder implementations for search result highlighting.
*/
public class HighlightBuilderProtoUtils {
class HighlightBuilderProtoUtils {

private HighlightBuilderProtoUtils() {
// Utility class, no instances
Expand All @@ -25,21 +35,231 @@ private HighlightBuilderProtoUtils() {
/**
* Converts a Protocol Buffer Highlight to an OpenSearch HighlightBuilder.
* Similar to {@link HighlightBuilder#fromXContent(XContentParser)}, this method
* would parse the Protocol Buffer representation and create a properly configured
* parses the Protocol Buffer representation and creates a properly configured
* HighlightBuilder with the appropriate settings.
*
* @param highlightProto The Protocol Buffer Highlight to convert
* @return A configured HighlightBuilder instance
* @throws UnsupportedOperationException as highlight functionality is not yet implemented
* @throws IllegalArgumentException if highlightProto is null
*/
protected static HighlightBuilder fromProto(Highlight highlightProto) {
static HighlightBuilder fromProto(Highlight highlightProto, QueryBuilderProtoConverterRegistry registry) {
if (highlightProto == null) {
throw new IllegalArgumentException("Highlight cannot be null");
}

throw new UnsupportedOperationException("highlight not supported yet");

/*
HighlightBuilder highlightBuilder = new HighlightBuilder();
// TODO populate highlightBuilder

if (highlightProto.getPreTagsCount() > 0) {
String[] preTags = new String[highlightProto.getPreTagsCount()];
for (int i = 0; i < highlightProto.getPreTagsCount(); i++) {
preTags[i] = highlightProto.getPreTags(i);
}
highlightBuilder.preTags(preTags);
}

if (highlightProto.getPostTagsCount() > 0) {
String[] postTags = new String[highlightProto.getPostTagsCount()];
for (int i = 0; i < highlightProto.getPostTagsCount(); i++) {
postTags[i] = highlightProto.getPostTags(i);
}
highlightBuilder.postTags(postTags);
}

if (highlightProto.hasOrder() && highlightProto.getOrder() == HighlighterOrder.HIGHLIGHTER_ORDER_SCORE) {
highlightBuilder.order(HighlightBuilder.Order.SCORE);
}

if (highlightProto.hasHighlightFilter()) {
highlightBuilder.highlightFilter(highlightProto.getHighlightFilter());
}

if (highlightProto.hasFragmentSize()) {
highlightBuilder.fragmentSize(highlightProto.getFragmentSize());
}

if (highlightProto.hasNumberOfFragments()) {
highlightBuilder.numOfFragments(highlightProto.getNumberOfFragments());
}

if (highlightProto.hasRequireFieldMatch()) {
highlightBuilder.requireFieldMatch(highlightProto.getRequireFieldMatch());
}

if (highlightProto.hasBoundaryScanner()) {
HighlightBuilder.BoundaryScannerType boundaryScanner = parseBoundaryScanner(highlightProto.getBoundaryScanner());
if (boundaryScanner != null) {
highlightBuilder.boundaryScannerType(boundaryScanner);
}
}

if (highlightProto.hasBoundaryMaxScan()) {
highlightBuilder.boundaryMaxScan(highlightProto.getBoundaryMaxScan());
}

if (highlightProto.hasBoundaryChars()) {
highlightBuilder.boundaryChars(highlightProto.getBoundaryChars().toCharArray());
}

if (highlightProto.hasBoundaryScannerLocale()) {
highlightBuilder.boundaryScannerLocale(highlightProto.getBoundaryScannerLocale());
}

if (highlightProto.hasType()) {
if (highlightProto.getType().hasBuiltin()
&& highlightProto.getType().getBuiltin() != BuiltinHighlighterType.BUILTIN_HIGHLIGHTER_TYPE_UNSPECIFIED) {
highlightBuilder.highlighterType(ProtobufEnumUtils.convertToString(highlightProto.getType().getBuiltin()));
} else if (highlightProto.getType().hasCustom()) {
highlightBuilder.highlighterType(highlightProto.getType().getCustom());
}
}

if (highlightProto.hasFragmenter() && highlightProto.getFragmenter() != HighlighterFragmenter.HIGHLIGHTER_FRAGMENTER_UNSPECIFIED) {
highlightBuilder.fragmenter(ProtobufEnumUtils.convertToString(highlightProto.getFragmenter()));
}

if (highlightProto.hasNoMatchSize()) {
highlightBuilder.noMatchSize(highlightProto.getNoMatchSize());
}

if (highlightProto.hasForceSource()) {
highlightBuilder.forceSource(highlightProto.getForceSource());
}

if (highlightProto.hasPhraseLimit()) {
highlightBuilder.phraseLimit(highlightProto.getPhraseLimit());
}

if (highlightProto.hasMaxAnalyzedOffset()) {
highlightBuilder.maxAnalyzerOffset(highlightProto.getMaxAnalyzedOffset());
}

if (highlightProto.hasOptions()) {
highlightBuilder.options(ObjectMapProtoUtils.fromProto(highlightProto.getOptions()));
}

if (highlightProto.hasHighlightQuery()) {
if (registry == null) {
throw new IllegalStateException("QueryBuilderProtoConverterRegistry cannot be null.");
}
QueryBuilder query = registry.fromProto(highlightProto.getHighlightQuery());
highlightBuilder.highlightQuery(query);
}

if (highlightProto.hasTagsSchema() && highlightProto.getTagsSchema() != HighlighterTagsSchema.HIGHLIGHTER_TAGS_SCHEMA_UNSPECIFIED) {
highlightBuilder.tagsSchema(ProtobufEnumUtils.convertToString(highlightProto.getTagsSchema()));
}

if (highlightProto.hasEncoder() && highlightProto.getEncoder() != HighlighterEncoder.HIGHLIGHTER_ENCODER_UNSPECIFIED) {
highlightBuilder.encoder(ProtobufEnumUtils.convertToString(highlightProto.getEncoder()));
}

if (highlightProto.getFieldsCount() > 0) {
for (java.util.Map.Entry<String, org.opensearch.protobufs.HighlightField> entry : highlightProto.getFieldsMap().entrySet()) {
String fieldName = entry.getKey();
org.opensearch.protobufs.HighlightField fieldProto = entry.getValue();

HighlightBuilder.Field fieldBuilder = new HighlightBuilder.Field(fieldName);

if (fieldProto.hasFragmentOffset()) {
fieldBuilder.fragmentOffset(fieldProto.getFragmentOffset());
}

if (fieldProto.getMatchedFieldsCount() > 0) {
String[] matchedFields = new String[fieldProto.getMatchedFieldsCount()];
for (int j = 0; j < fieldProto.getMatchedFieldsCount(); j++) {
matchedFields[j] = fieldProto.getMatchedFields(j);
}
fieldBuilder.matchedFields(matchedFields);
}

if (fieldProto.hasType()) {
if (fieldProto.getType().hasBuiltin()
&& fieldProto.getType().getBuiltin() != BuiltinHighlighterType.BUILTIN_HIGHLIGHTER_TYPE_UNSPECIFIED) {
fieldBuilder.highlighterType(ProtobufEnumUtils.convertToString(fieldProto.getType().getBuiltin()));
} else if (fieldProto.getType().hasCustom()) {
fieldBuilder.highlighterType(fieldProto.getType().getCustom());
}
}

if (fieldProto.hasBoundaryChars()) {
fieldBuilder.boundaryChars(fieldProto.getBoundaryChars().toCharArray());
}

if (fieldProto.hasBoundaryMaxScan()) {
fieldBuilder.boundaryMaxScan(fieldProto.getBoundaryMaxScan());
}

if (fieldProto.hasBoundaryScanner()) {
HighlightBuilder.BoundaryScannerType boundaryScanner = parseBoundaryScanner(fieldProto.getBoundaryScanner());
if (boundaryScanner != null) {
fieldBuilder.boundaryScannerType(boundaryScanner);
}
}

if (fieldProto.hasBoundaryScannerLocale()) {
fieldBuilder.boundaryScannerLocale(fieldProto.getBoundaryScannerLocale());
}

if (fieldProto.hasFragmenter() && fieldProto.getFragmenter() != HighlighterFragmenter.HIGHLIGHTER_FRAGMENTER_UNSPECIFIED) {
fieldBuilder.fragmenter(ProtobufEnumUtils.convertToString(fieldProto.getFragmenter()));
}

if (fieldProto.hasFragmentSize()) {
fieldBuilder.fragmentSize(fieldProto.getFragmentSize());
}

if (fieldProto.hasHighlightFilter()) {
fieldBuilder.highlightFilter(fieldProto.getHighlightFilter());
}

if (fieldProto.hasHighlightQuery()) {
if (registry == null) {
throw new IllegalStateException("QueryBuilderProtoConverterRegistry cannot be null.");
}
QueryBuilder query = registry.fromProto(fieldProto.getHighlightQuery());
fieldBuilder.highlightQuery(query);
}

if (fieldProto.hasNoMatchSize()) {
fieldBuilder.noMatchSize(fieldProto.getNoMatchSize());
}

if (fieldProto.hasNumberOfFragments()) {
fieldBuilder.numOfFragments(fieldProto.getNumberOfFragments());
}

if (fieldProto.hasOptions()) {
fieldBuilder.options(ObjectMapProtoUtils.fromProto(fieldProto.getOptions()));
}
if (fieldProto.hasMaxAnalyzedOffset()) {
fieldBuilder.maxAnalyzerOffset(fieldProto.getMaxAnalyzedOffset());
}

highlightBuilder.field(fieldBuilder);
}
}

return highlightBuilder;
*/
}

/**
* Convert protobuf BoundaryScanner enum to OpenSearch BoundaryScannerType enum
*/
private static HighlightBuilder.BoundaryScannerType parseBoundaryScanner(BoundaryScanner boundaryScanner) {
if (boundaryScanner == null) {
return null;
}
switch (boundaryScanner) {
case BOUNDARY_SCANNER_CHARS:
return HighlightBuilder.BoundaryScannerType.CHARS;
case BOUNDARY_SCANNER_WORD:
return HighlightBuilder.BoundaryScannerType.WORD;
case BOUNDARY_SCANNER_SENTENCE:
return HighlightBuilder.BoundaryScannerType.SENTENCE;
case BOUNDARY_SCANNER_UNSPECIFIED:
case UNRECOGNIZED:
default:
return null; // use its default
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.opensearch.search.fetch.subphase.FieldAndFormat;
import org.opensearch.transport.grpc.proto.request.common.FetchSourceContextProtoUtils;
import org.opensearch.transport.grpc.proto.request.search.sort.SortBuilderProtoUtils;
import org.opensearch.transport.grpc.spi.QueryBuilderProtoConverterRegistry;

import java.io.IOException;
import java.util.ArrayList;
Expand All @@ -37,10 +38,11 @@ private InnerHitsBuilderProtoUtils() {
* Each InnerHits protobuf message represents ONE inner hit definition.
*
* @param innerHits the protobuf InnerHits to convert
* @param registry The registry for query conversion (needed for sorts and highlights with queries)
* @return the converted OpenSearch InnerHitBuilder
* @throws IOException if there's an error during parsing
*/
public static InnerHitBuilder fromProto(InnerHits innerHits) throws IOException {
public static InnerHitBuilder fromProto(InnerHits innerHits, QueryBuilderProtoConverterRegistry registry) throws IOException {
if (innerHits == null) {
throw new IllegalArgumentException("InnerHits cannot be null");
}
Expand Down Expand Up @@ -102,16 +104,16 @@ public static InnerHitBuilder fromProto(InnerHits innerHits) throws IOException
innerHitBuilder.setScriptFields(scriptFields);
}
if (innerHits.getSortCount() > 0) {
innerHitBuilder.setSorts(SortBuilderProtoUtils.fromProto(innerHits.getSortList()));
innerHitBuilder.setSorts(SortBuilderProtoUtils.fromProto(innerHits.getSortList(), registry));
}
if (innerHits.hasXSource()) {
innerHitBuilder.setFetchSourceContext(FetchSourceContextProtoUtils.fromProto(innerHits.getXSource()));
}
if (innerHits.hasHighlight()) {
innerHitBuilder.setHighlightBuilder(HighlightBuilderProtoUtils.fromProto(innerHits.getHighlight()));
innerHitBuilder.setHighlightBuilder(HighlightBuilderProtoUtils.fromProto(innerHits.getHighlight(), registry));
}
if (innerHits.hasCollapse()) {
innerHitBuilder.setInnerCollapse(CollapseBuilderProtoUtils.fromProto(innerHits.getCollapse()));
innerHitBuilder.setInnerCollapse(CollapseBuilderProtoUtils.fromProto(innerHits.getCollapse(), registry));
}

return innerHitBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static org.opensearch.action.search.SearchRequest prepareRequest(
* @param queryUtils the query utils instance for parsing queries
* @throws IOException if an I/O exception occurred during parsing
*/
protected static void parseSearchRequest(
static void parseSearchRequest(
org.opensearch.action.search.SearchRequest searchRequest,
org.opensearch.protobufs.SearchRequest request,
NamedWriteableRegistry namedWriteableRegistry,
Expand Down Expand Up @@ -196,7 +196,7 @@ protected static void parseSearchRequest(
* @param request the Protocol Buffer SearchRequest to parse
* @param setSize consumer for setting the size parameter
*/
protected static void parseSearchSource(
static void parseSearchSource(
final SearchSourceBuilder searchSourceBuilder,
org.opensearch.protobufs.SearchRequest request,
IntConsumer setSize
Expand Down Expand Up @@ -346,7 +346,7 @@ private static void preparePointInTime(
* @param protoRequest the Protocol Buffer SearchRequest
* @param searchRequest the SearchRequest to configure
*/
protected static void checkProtoTotalHits(SearchRequest protoRequest, org.opensearch.action.search.SearchRequest searchRequest) {
static void checkProtoTotalHits(SearchRequest protoRequest, org.opensearch.action.search.SearchRequest searchRequest) {

boolean totalHitsAsInt = protoRequest.hasRestTotalHitsAsInt() ? protoRequest.getRestTotalHitsAsInt() : false;
if (totalHitsAsInt == false) {
Expand Down
Loading
Loading