[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
This commit is contained in:
Itamar Syn-Hershko 2014-07-07 00:12:54 +03:00 committed by Simon Willnauer
parent d403e68f43
commit dd0b42838d
3 changed files with 35 additions and 25 deletions

View File

@ -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<String> 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()]));
}
}

View File

@ -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<Tuple<String, SearchContextHighlight.FieldOptions.Builder>> fieldsOptions = newArrayList();
final List<Tuple<String, SearchContextHighlight.FieldOptions.Builder>> 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<SearchContextHighlight.Field> fields = Lists.newArrayList();
final List<SearchContextHighlight.Field> fields = Lists.newArrayList();
// now, go over and fill all fieldsOptions with default values from the global state
for (Tuple<String, SearchContextHighlight.FieldOptions.Builder> tuple : fieldsOptions) {
for (final Tuple<String, SearchContextHighlight.FieldOptions.Builder> 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());
}

View File

@ -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;