From dd0b42838d1015aefccec0b1af5e5bb0cf49b287 Mon Sep 17 00:00:00 2001 From: Itamar Syn-Hershko Date: Mon, 7 Jul 2014 00:12:54 +0300 Subject: [PATCH] [QUERY] Separate parsing impl from setter in SearchParseElement This commit makes it easier to reuse the inner highlighting, fetch and rescore parsing logic by plugins or other internal parts. Closes #3602 --- .../fetch/source/FetchSourceParseElement.java | 17 ++++---- .../highlight/HighlighterParseElement.java | 41 +++++++++++-------- .../search/rescore/RescoreParseElement.java | 2 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/elasticsearch/search/fetch/source/FetchSourceParseElement.java b/src/main/java/org/elasticsearch/search/fetch/source/FetchSourceParseElement.java index e3de3ab63eb..2cf5e9a6a68 100644 --- a/src/main/java/org/elasticsearch/search/fetch/source/FetchSourceParseElement.java +++ b/src/main/java/org/elasticsearch/search/fetch/source/FetchSourceParseElement.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.internal.SearchContext; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -43,17 +44,19 @@ public class FetchSourceParseElement implements SearchParseElement { @Override public void parse(XContentParser parser, SearchContext context) throws Exception { + context.fetchSourceContext(parse(parser)); + } + + public FetchSourceContext parse(XContentParser parser) throws IOException { XContentParser.Token token; List includes = null, excludes = null; String currentFieldName = null; token = parser.currentToken(); // we get it on the value if (parser.isBooleanValue()) { - context.fetchSourceContext(new FetchSourceContext(parser.booleanValue())); - return; + return new FetchSourceContext(parser.booleanValue()); } else if (token == XContentParser.Token.VALUE_STRING) { - context.fetchSourceContext(new FetchSourceContext(new String[]{parser.text()})); - return; + return new FetchSourceContext(new String[]{parser.text()}); } else if (token == XContentParser.Token.START_ARRAY) { includes = new ArrayList<>(); while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { @@ -87,10 +90,8 @@ public class FetchSourceParseElement implements SearchParseElement { throw new ElasticsearchParseException("source element value can be of type " + token.name()); } - - context.fetchSourceContext(new FetchSourceContext( + return new FetchSourceContext( includes == null ? Strings.EMPTY_ARRAY : includes.toArray(new String[includes.size()]), - excludes == null ? Strings.EMPTY_ARRAY : excludes.toArray(new String[excludes.size()]))); - + excludes == null ? Strings.EMPTY_ARRAY : excludes.toArray(new String[excludes.size()])); } } diff --git a/src/main/java/org/elasticsearch/search/highlight/HighlighterParseElement.java b/src/main/java/org/elasticsearch/search/highlight/HighlighterParseElement.java index ccd0e7c87ef..24adef3bba5 100644 --- a/src/main/java/org/elasticsearch/search/highlight/HighlighterParseElement.java +++ b/src/main/java/org/elasticsearch/search/highlight/HighlighterParseElement.java @@ -22,8 +22,10 @@ package org.elasticsearch.search.highlight; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.lucene.search.vectorhighlight.SimpleBoundaryScanner; +import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.query.IndexQueryParserService; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.SearchParseException; import org.elasticsearch.search.internal.SearchContext; @@ -66,11 +68,19 @@ public class HighlighterParseElement implements SearchParseElement { @Override public void parse(XContentParser parser, SearchContext context) throws Exception { + try { + context.highlight(parse(parser, context.queryParserService())); + } catch (ElasticsearchIllegalArgumentException ex) { + throw new SearchParseException(context, "Error while trying to parse Highlighter element in request"); + } + } + + public SearchContextHighlight parse(XContentParser parser, IndexQueryParserService queryParserService) throws IOException { XContentParser.Token token; String topLevelFieldName = null; - List> fieldsOptions = newArrayList(); + final List> fieldsOptions = newArrayList(); - SearchContextHighlight.FieldOptions.Builder globalOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder() + final SearchContextHighlight.FieldOptions.Builder globalOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder() .preTags(DEFAULT_PRE_TAGS).postTags(DEFAULT_POST_TAGS).scoreOrdered(false).highlightFilter(false) .requireFieldMatch(false).forceSource(false).fragmentCharSize(100).numberOfFragments(5) .encoder("default").boundaryMaxScan(SimpleBoundaryScanner.DEFAULT_MAX_SCAN) @@ -100,15 +110,15 @@ public class HighlighterParseElement implements SearchParseElement { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { if (highlightFieldName != null) { - throw new SearchParseException(context, "If highlighter fields is an array it must contain objects containing a single field"); + throw new ElasticsearchIllegalArgumentException("If highlighter fields is an array it must contain objects containing a single field"); } highlightFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - fieldsOptions.add(Tuple.tuple(highlightFieldName, parseFields(parser, context))); + fieldsOptions.add(Tuple.tuple(highlightFieldName, parseFields(parser, queryParserService))); } } } else { - throw new SearchParseException(context, "If highlighter fields is an array it must contain objects containing a single field"); + throw new ElasticsearchIllegalArgumentException("If highlighter fields is an array it must contain objects containing a single field"); } } } @@ -160,33 +170,32 @@ public class HighlighterParseElement implements SearchParseElement { if (token == XContentParser.Token.FIELD_NAME) { highlightFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - fieldsOptions.add(Tuple.tuple(highlightFieldName, parseFields(parser, context))); + fieldsOptions.add(Tuple.tuple(highlightFieldName, parseFields(parser, queryParserService))); } } } else if ("highlight_query".equals(topLevelFieldName) || "highlightQuery".equals(topLevelFieldName)) { - globalOptionsBuilder.highlightQuery(context.queryParserService().parse(parser).query()); + globalOptionsBuilder.highlightQuery(queryParserService.parse(parser).query()); } } } - SearchContextHighlight.FieldOptions globalOptions = globalOptionsBuilder.build(); + final SearchContextHighlight.FieldOptions globalOptions = globalOptionsBuilder.build(); if (globalOptions.preTags() != null && globalOptions.postTags() == null) { - throw new SearchParseException(context, "Highlighter global preTags are set, but global postTags are not set"); + throw new ElasticsearchIllegalArgumentException("Highlighter global preTags are set, but global postTags are not set"); } - List fields = Lists.newArrayList(); + final List fields = Lists.newArrayList(); // now, go over and fill all fieldsOptions with default values from the global state - for (Tuple tuple : fieldsOptions) { + for (final Tuple tuple : fieldsOptions) { fields.add(new SearchContextHighlight.Field(tuple.v1(), tuple.v2().merge(globalOptions).build())); } - - context.highlight(new SearchContextHighlight(fields)); + return new SearchContextHighlight(fields); } - private SearchContextHighlight.FieldOptions.Builder parseFields(XContentParser parser, SearchContext context) throws IOException { + protected SearchContextHighlight.FieldOptions.Builder parseFields(XContentParser parser, IndexQueryParserService queryParserService) throws IOException { XContentParser.Token token; - SearchContextHighlight.FieldOptions.Builder fieldOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder(); + final SearchContextHighlight.FieldOptions.Builder fieldOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder(); String fieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { @@ -246,7 +255,7 @@ public class HighlighterParseElement implements SearchParseElement { } } else if (token == XContentParser.Token.START_OBJECT) { if ("highlight_query".equals(fieldName) || "highlightQuery".equals(fieldName)) { - fieldOptionsBuilder.highlightQuery(context.queryParserService().parse(parser).query()); + fieldOptionsBuilder.highlightQuery(queryParserService.parse(parser).query()); } else if ("options".equals(fieldName)) { fieldOptionsBuilder.options(parser.map()); } diff --git a/src/main/java/org/elasticsearch/search/rescore/RescoreParseElement.java b/src/main/java/org/elasticsearch/search/rescore/RescoreParseElement.java index 9168c22e6ea..f87165e584b 100644 --- a/src/main/java/org/elasticsearch/search/rescore/RescoreParseElement.java +++ b/src/main/java/org/elasticsearch/search/rescore/RescoreParseElement.java @@ -41,7 +41,7 @@ public class RescoreParseElement implements SearchParseElement { } } - private void parseSingleRescoreContext(XContentParser parser, SearchContext context) throws Exception { + public void parseSingleRescoreContext(XContentParser parser, SearchContext context) throws Exception { String fieldName = null; RescoreSearchContext rescoreContext = null; Integer windowSize = null;