Merge pull request #15368 from cbuescher/highlight-builder-shared-parsing
Joint parsing of common global Hightlighter and subfield parameters
This commit is contained in:
commit
7742c1e181
|
@ -22,13 +22,17 @@ package org.elasticsearch.search.highlight;
|
||||||
import org.apache.lucene.search.highlight.SimpleFragmenter;
|
import org.apache.lucene.search.highlight.SimpleFragmenter;
|
||||||
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
|
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
|
||||||
import org.elasticsearch.common.ParseField;
|
import org.elasticsearch.common.ParseField;
|
||||||
|
import org.elasticsearch.common.ParsingException;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.query.QueryBuilder;
|
import org.elasticsearch.index.query.QueryBuilder;
|
||||||
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -419,6 +423,100 @@ public abstract class AbstractHighlighterBuilder<HB extends AbstractHighlighterB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link HighlightBuilder} from the highlighter held by the {@link QueryParseContext}
|
||||||
|
* in {@link org.elasticsearch.common.xcontent.XContent} format
|
||||||
|
*
|
||||||
|
* @param parseContext containing the parser positioned at the structure to be parsed from.
|
||||||
|
* the state on the parser contained in this context will be changed as a side effect of this
|
||||||
|
* method call
|
||||||
|
* @return the new {@link AbstractHighlighterBuilder}
|
||||||
|
*/
|
||||||
|
public HB fromXContent(QueryParseContext parseContext) throws IOException {
|
||||||
|
XContentParser parser = parseContext.parser();
|
||||||
|
XContentParser.Token token = parser.currentToken();
|
||||||
|
String currentFieldName = null;
|
||||||
|
HB highlightBuilder = createInstance(parser);
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
currentFieldName = parser.currentName();
|
||||||
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
|
if (parseContext.parseFieldMatcher().match(currentFieldName, PRE_TAGS_FIELD)) {
|
||||||
|
List<String> preTagsList = new ArrayList<>();
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
preTagsList.add(parser.text());
|
||||||
|
}
|
||||||
|
highlightBuilder.preTags(preTagsList.toArray(new String[preTagsList.size()]));
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, POST_TAGS_FIELD)) {
|
||||||
|
List<String> postTagsList = new ArrayList<>();
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
postTagsList.add(parser.text());
|
||||||
|
}
|
||||||
|
highlightBuilder.postTags(postTagsList.toArray(new String[postTagsList.size()]));
|
||||||
|
} else if (false == highlightBuilder.doFromXContent(parseContext, currentFieldName, token)) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "cannot parse array with name [{}]", currentFieldName);
|
||||||
|
}
|
||||||
|
} else if (token.isValue()) {
|
||||||
|
if (parseContext.parseFieldMatcher().match(currentFieldName, ORDER_FIELD)) {
|
||||||
|
highlightBuilder.order(parser.text());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, HIGHLIGHT_FILTER_FIELD)) {
|
||||||
|
highlightBuilder.highlightFilter(parser.booleanValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENT_SIZE_FIELD)) {
|
||||||
|
highlightBuilder.fragmentSize(parser.intValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, NUMBER_OF_FRAGMENTS_FIELD)) {
|
||||||
|
highlightBuilder.numOfFragments(parser.intValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, REQUIRE_FIELD_MATCH_FIELD)) {
|
||||||
|
highlightBuilder.requireFieldMatch(parser.booleanValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, BOUNDARY_MAX_SCAN_FIELD)) {
|
||||||
|
highlightBuilder.boundaryMaxScan(parser.intValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, BOUNDARY_CHARS_FIELD)) {
|
||||||
|
highlightBuilder.boundaryChars(parser.text().toCharArray());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, TYPE_FIELD)) {
|
||||||
|
highlightBuilder.highlighterType(parser.text());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENTER_FIELD)) {
|
||||||
|
highlightBuilder.fragmenter(parser.text());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, NO_MATCH_SIZE_FIELD)) {
|
||||||
|
highlightBuilder.noMatchSize(parser.intValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FORCE_SOURCE_FIELD)) {
|
||||||
|
highlightBuilder.forceSource(parser.booleanValue());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, PHRASE_LIMIT_FIELD)) {
|
||||||
|
highlightBuilder.phraseLimit(parser.intValue());
|
||||||
|
} else if (false == highlightBuilder.doFromXContent(parseContext, currentFieldName, token)) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "unexpected fieldname [{}]", currentFieldName);
|
||||||
|
}
|
||||||
|
} else if (token == XContentParser.Token.START_OBJECT && currentFieldName != null) {
|
||||||
|
if (parseContext.parseFieldMatcher().match(currentFieldName, OPTIONS_FIELD)) {
|
||||||
|
highlightBuilder.options(parser.map());
|
||||||
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, HIGHLIGHT_QUERY_FIELD)) {
|
||||||
|
highlightBuilder.highlightQuery(parseContext.parseInnerQueryBuilder());
|
||||||
|
} else if (false == highlightBuilder.doFromXContent(parseContext, currentFieldName, token)) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "cannot parse object with name [{}]", currentFieldName);
|
||||||
|
}
|
||||||
|
} else if (currentFieldName != null) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "unexpected token [{}] after [{}]", token, currentFieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highlightBuilder.preTags() != null && highlightBuilder.postTags() == null) {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "Highlighter global preTags are set, but global postTags are not set");
|
||||||
|
}
|
||||||
|
return highlightBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parser the input parser. Implementing classes might advance the parser depending on the
|
||||||
|
* information they need to instantiate a new instance
|
||||||
|
* @return a new instance
|
||||||
|
*/
|
||||||
|
protected abstract HB createInstance(XContentParser parser) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementing subclasses can handle parsing special options depending on the
|
||||||
|
* current token, field name and the parse context.
|
||||||
|
* @return <tt>true</tt> if an option was found and successfully parsed, otherwise <tt>false</tt>
|
||||||
|
*/
|
||||||
|
protected abstract boolean doFromXContent(QueryParseContext parseContext, String currentFieldName, XContentParser.Token endMarkerToken) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public final int hashCode() {
|
||||||
return Objects.hash(getClass(), Arrays.hashCode(preTags), Arrays.hashCode(postTags), fragmentSize,
|
return Objects.hash(getClass(), Arrays.hashCode(preTags), Arrays.hashCode(postTags), fragmentSize,
|
||||||
|
|
|
@ -30,11 +30,13 @@ import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentParser.Token;
|
||||||
import org.elasticsearch.index.query.QueryBuilder;
|
import org.elasticsearch.index.query.QueryBuilder;
|
||||||
import org.elasticsearch.index.query.QueryParseContext;
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
||||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions.Builder;
|
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions.Builder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -230,117 +232,45 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link HighlightBuilder} from the highlighter held by the {@link QueryParseContext}
|
* parse options only present in top level highlight builder (`tags_schema`, `encoder` and nested `fields`)
|
||||||
* in {@link org.elasticsearch.common.xcontent.XContent} format
|
|
||||||
*
|
|
||||||
* @param parseContext
|
|
||||||
* the input parse context. The state on the parser contained in
|
|
||||||
* this context will be changed as a side effect of this method
|
|
||||||
* call
|
|
||||||
* @return the new {@link HighlightBuilder}
|
|
||||||
*/
|
*/
|
||||||
public static HighlightBuilder fromXContent(QueryParseContext parseContext) throws IOException {
|
@Override
|
||||||
|
protected boolean doFromXContent(QueryParseContext parseContext, String currentFieldName, Token currentToken) throws IOException {
|
||||||
XContentParser parser = parseContext.parser();
|
XContentParser parser = parseContext.parser();
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
String topLevelFieldName = null;
|
boolean foundCurrentFieldMatch = false;
|
||||||
|
if (currentToken.isValue()) {
|
||||||
HighlightBuilder highlightBuilder = new HighlightBuilder();
|
if (parseContext.parseFieldMatcher().match(currentFieldName, TAGS_SCHEMA_FIELD)) {
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
tagsSchema(parser.text());
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
foundCurrentFieldMatch = true;
|
||||||
topLevelFieldName = parser.currentName();
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, ENCODER_FIELD)) {
|
||||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
encoder(parser.text());
|
||||||
if (parseContext.parseFieldMatcher().match(topLevelFieldName, PRE_TAGS_FIELD)) {
|
foundCurrentFieldMatch = true;
|
||||||
List<String> preTagsList = new ArrayList<>();
|
}
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
} else if (currentToken == Token.START_ARRAY && parseContext.parseFieldMatcher().match(currentFieldName, FIELDS_FIELD)) {
|
||||||
preTagsList.add(parser.text());
|
useExplicitFieldOrder(true);
|
||||||
}
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
highlightBuilder.preTags(preTagsList.toArray(new String[preTagsList.size()]));
|
if (token == XContentParser.Token.START_OBJECT) {
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, POST_TAGS_FIELD)) {
|
|
||||||
List<String> postTagsList = new ArrayList<>();
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
||||||
postTagsList.add(parser.text());
|
|
||||||
}
|
|
||||||
highlightBuilder.postTags(postTagsList.toArray(new String[postTagsList.size()]));
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, FIELDS_FIELD)) {
|
|
||||||
highlightBuilder.useExplicitFieldOrder(true);
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
||||||
if (token == XContentParser.Token.START_OBJECT) {
|
|
||||||
String highlightFieldName = null;
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
|
||||||
if (highlightFieldName != null) {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "If highlighter fields is an array it must contain objects containing a single field");
|
|
||||||
}
|
|
||||||
highlightFieldName = parser.currentName();
|
|
||||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
|
||||||
highlightBuilder.field(Field.fromXContent(highlightFieldName, parseContext));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "If highlighter fields is an array it must contain objects containing a single field");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "cannot parse array with name [{}]", topLevelFieldName);
|
|
||||||
}
|
|
||||||
} else if (token.isValue()) {
|
|
||||||
if (parseContext.parseFieldMatcher().match(topLevelFieldName, ORDER_FIELD)) {
|
|
||||||
highlightBuilder.order(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, TAGS_SCHEMA_FIELD)) {
|
|
||||||
highlightBuilder.tagsSchema(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, HIGHLIGHT_FILTER_FIELD)) {
|
|
||||||
highlightBuilder.highlightFilter(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, FRAGMENT_SIZE_FIELD)) {
|
|
||||||
highlightBuilder.fragmentSize(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, NUMBER_OF_FRAGMENTS_FIELD)) {
|
|
||||||
highlightBuilder.numOfFragments(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, ENCODER_FIELD)) {
|
|
||||||
highlightBuilder.encoder(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, REQUIRE_FIELD_MATCH_FIELD)) {
|
|
||||||
highlightBuilder.requireFieldMatch(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, BOUNDARY_MAX_SCAN_FIELD)) {
|
|
||||||
highlightBuilder.boundaryMaxScan(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, BOUNDARY_CHARS_FIELD)) {
|
|
||||||
highlightBuilder.boundaryChars(parser.text().toCharArray());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, TYPE_FIELD)) {
|
|
||||||
highlightBuilder.highlighterType(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, FRAGMENTER_FIELD)) {
|
|
||||||
highlightBuilder.fragmenter(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, NO_MATCH_SIZE_FIELD)) {
|
|
||||||
highlightBuilder.noMatchSize(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, FORCE_SOURCE_FIELD)) {
|
|
||||||
highlightBuilder.forceSource(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, PHRASE_LIMIT_FIELD)) {
|
|
||||||
highlightBuilder.phraseLimit(parser.intValue());
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "unexpected fieldname [{}]", topLevelFieldName);
|
|
||||||
}
|
|
||||||
} else if (token == XContentParser.Token.START_OBJECT && topLevelFieldName != null) {
|
|
||||||
if (parseContext.parseFieldMatcher().match(topLevelFieldName, OPTIONS_FIELD)) {
|
|
||||||
highlightBuilder.options(parser.map());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, FIELDS_FIELD)) {
|
|
||||||
String highlightFieldName = null;
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
highlightFieldName = parser.currentName();
|
field(HighlightBuilder.Field.PROTOTYPE.fromXContent(parseContext));
|
||||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
|
||||||
highlightBuilder.field(Field.fromXContent(highlightFieldName, parseContext));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (parseContext.parseFieldMatcher().match(topLevelFieldName, HIGHLIGHT_QUERY_FIELD)) {
|
foundCurrentFieldMatch = true;
|
||||||
highlightBuilder.highlightQuery(parseContext.parseInnerQueryBuilder());
|
|
||||||
} else {
|
} else {
|
||||||
throw new ParsingException(parser.getTokenLocation(), "cannot parse object with name [{}]", topLevelFieldName);
|
throw new ParsingException(parser.getTokenLocation(),
|
||||||
|
"If highlighter fields is an array it must contain objects containing a single field");
|
||||||
}
|
}
|
||||||
} else if (topLevelFieldName != null) {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "unexpected token [{}] after [{}]", token, topLevelFieldName);
|
|
||||||
}
|
}
|
||||||
|
} else if (currentToken == Token.START_OBJECT && parseContext.parseFieldMatcher().match(currentFieldName, FIELDS_FIELD)) {
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
field(HighlightBuilder.Field.PROTOTYPE.fromXContent(parseContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundCurrentFieldMatch = true;
|
||||||
}
|
}
|
||||||
|
return foundCurrentFieldMatch;
|
||||||
if (highlightBuilder.preTags() != null && highlightBuilder.postTags() == null) {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "Highlighter global preTags are set, but global postTags are not set");
|
|
||||||
}
|
|
||||||
return highlightBuilder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchContextHighlight build(QueryShardContext context) throws IOException {
|
public SearchContextHighlight build(QueryShardContext context) throws IOException {
|
||||||
|
@ -467,6 +397,11 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HighlightBuilder createInstance(XContentParser parser) {
|
||||||
|
return new HighlightBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int doHashCode() {
|
protected int doHashCode() {
|
||||||
return Objects.hash(encoder, useExplicitFieldOrder, fields);
|
return Objects.hash(encoder, useExplicitFieldOrder, fields);
|
||||||
|
@ -549,80 +484,36 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HighlightBuilder.Field fromXContent(String fieldname, QueryParseContext parseContext) throws IOException {
|
/**
|
||||||
|
* parse options only present in field highlight builder (`fragment_offset`, `matched_fields`)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean doFromXContent(QueryParseContext parseContext, String currentFieldName, Token currentToken) throws IOException {
|
||||||
XContentParser parser = parseContext.parser();
|
XContentParser parser = parseContext.parser();
|
||||||
XContentParser.Token token;
|
boolean foundCurrentFieldMatch = false;
|
||||||
|
if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENT_OFFSET_FIELD) && currentToken.isValue()) {
|
||||||
final HighlightBuilder.Field field = new HighlightBuilder.Field(fieldname);
|
fragmentOffset(parser.intValue());
|
||||||
String currentFieldName = null;
|
foundCurrentFieldMatch = true;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, MATCHED_FIELDS_FIELD)
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
&& currentToken == XContentParser.Token.START_ARRAY) {
|
||||||
currentFieldName = parser.currentName();
|
List<String> matchedFields = new ArrayList<>();
|
||||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||||
if (parseContext.parseFieldMatcher().match(currentFieldName, PRE_TAGS_FIELD)) {
|
matchedFields.add(parser.text());
|
||||||
List<String> preTagsList = new ArrayList<>();
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
||||||
preTagsList.add(parser.text());
|
|
||||||
}
|
|
||||||
field.preTags(preTagsList.toArray(new String[preTagsList.size()]));
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, POST_TAGS_FIELD)) {
|
|
||||||
List<String> postTagsList = new ArrayList<>();
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
||||||
postTagsList.add(parser.text());
|
|
||||||
}
|
|
||||||
field.postTags(postTagsList.toArray(new String[postTagsList.size()]));
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, MATCHED_FIELDS_FIELD)) {
|
|
||||||
List<String> matchedFields = new ArrayList<>();
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
||||||
matchedFields.add(parser.text());
|
|
||||||
}
|
|
||||||
field.matchedFields(matchedFields.toArray(new String[matchedFields.size()]));
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "cannot parse array with name [{}]", currentFieldName);
|
|
||||||
}
|
|
||||||
} else if (token.isValue()) {
|
|
||||||
if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENT_SIZE_FIELD)) {
|
|
||||||
field.fragmentSize(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, NUMBER_OF_FRAGMENTS_FIELD)) {
|
|
||||||
field.numOfFragments(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENT_OFFSET_FIELD)) {
|
|
||||||
field.fragmentOffset(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, HIGHLIGHT_FILTER_FIELD)) {
|
|
||||||
field.highlightFilter(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, ORDER_FIELD)) {
|
|
||||||
field.order(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, REQUIRE_FIELD_MATCH_FIELD)) {
|
|
||||||
field.requireFieldMatch(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, BOUNDARY_MAX_SCAN_FIELD)) {
|
|
||||||
field.boundaryMaxScan(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, BOUNDARY_CHARS_FIELD)) {
|
|
||||||
field.boundaryChars(parser.text().toCharArray());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, TYPE_FIELD)) {
|
|
||||||
field.highlighterType(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FRAGMENTER_FIELD)) {
|
|
||||||
field.fragmenter(parser.text());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, NO_MATCH_SIZE_FIELD)) {
|
|
||||||
field.noMatchSize(parser.intValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FORCE_SOURCE_FIELD)) {
|
|
||||||
field.forceSource(parser.booleanValue());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, PHRASE_LIMIT_FIELD)) {
|
|
||||||
field.phraseLimit(parser.intValue());
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "unexpected fieldname [{}]", currentFieldName);
|
|
||||||
}
|
|
||||||
} else if (token == XContentParser.Token.START_OBJECT && currentFieldName != null) {
|
|
||||||
if (parseContext.parseFieldMatcher().match(currentFieldName, HIGHLIGHT_QUERY_FIELD)) {
|
|
||||||
field.highlightQuery(parseContext.parseInnerQueryBuilder());
|
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, OPTIONS_FIELD)) {
|
|
||||||
field.options(parser.map());
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "cannot parse object with name [{}]", currentFieldName);
|
|
||||||
}
|
|
||||||
} else if (currentFieldName != null) {
|
|
||||||
throw new ParsingException(parser.getTokenLocation(), "unexpected token [{}] after [{}]", token, currentFieldName);
|
|
||||||
}
|
}
|
||||||
|
matchedFields(matchedFields.toArray(new String[matchedFields.size()]));
|
||||||
|
foundCurrentFieldMatch = true;
|
||||||
|
}
|
||||||
|
return foundCurrentFieldMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Field createInstance(XContentParser parser) throws IOException {
|
||||||
|
if (parser.currentToken() == XContentParser.Token.FIELD_NAME) {
|
||||||
|
String fieldname = parser.currentName();
|
||||||
|
return new Field(fieldname);
|
||||||
|
} else {
|
||||||
|
throw new ParsingException(parser.getTokenLocation(), "unknown token type [{}], expected field name", parser.currentToken());
|
||||||
}
|
}
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
package org.elasticsearch.search.highlight;
|
package org.elasticsearch.search.highlight;
|
||||||
|
|
||||||
import org.elasticsearch.common.ParseFieldMatcher;
|
|
||||||
import org.elasticsearch.common.ParsingException;
|
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
|
import org.elasticsearch.common.ParseFieldMatcher;
|
||||||
|
import org.elasticsearch.common.ParsingException;
|
||||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||||
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
||||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||||
|
@ -52,7 +52,6 @@ import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||||
import org.elasticsearch.index.query.TermQueryParser;
|
import org.elasticsearch.index.query.TermQueryParser;
|
||||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
|
||||||
import org.elasticsearch.search.highlight.HighlightBuilder.Field;
|
import org.elasticsearch.search.highlight.HighlightBuilder.Field;
|
||||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
@ -149,6 +148,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
context.parseFieldMatcher(new ParseFieldMatcher(Settings.EMPTY));
|
context.parseFieldMatcher(new ParseFieldMatcher(Settings.EMPTY));
|
||||||
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
|
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
|
||||||
HighlightBuilder highlightBuilder = randomHighlighterBuilder();
|
HighlightBuilder highlightBuilder = randomHighlighterBuilder();
|
||||||
|
System.out.println(highlightBuilder);
|
||||||
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
|
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
builder.prettyPrint();
|
builder.prettyPrint();
|
||||||
|
@ -159,7 +159,8 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
HighlightBuilder secondHighlightBuilder = HighlightBuilder.fromXContent(context);
|
parser.nextToken();
|
||||||
|
HighlightBuilder secondHighlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
assertNotSame(highlightBuilder, secondHighlightBuilder);
|
assertNotSame(highlightBuilder, secondHighlightBuilder);
|
||||||
assertEquals(highlightBuilder, secondHighlightBuilder);
|
assertEquals(highlightBuilder, secondHighlightBuilder);
|
||||||
assertEquals(highlightBuilder.hashCode(), secondHighlightBuilder.hashCode());
|
assertEquals(highlightBuilder.hashCode(), secondHighlightBuilder.hashCode());
|
||||||
|
@ -179,7 +180,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("cannot parse array with name [bad_fieldname]", e.getMessage());
|
assertEquals("cannot parse array with name [bad_fieldname]", e.getMessage());
|
||||||
|
@ -196,7 +197,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("cannot parse array with name [bad_fieldname]", e.getMessage());
|
assertEquals("cannot parse array with name [bad_fieldname]", e.getMessage());
|
||||||
|
@ -216,7 +217,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("unexpected fieldname [bad_fieldname]", e.getMessage());
|
assertEquals("unexpected fieldname [bad_fieldname]", e.getMessage());
|
||||||
|
@ -233,7 +234,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("unexpected fieldname [bad_fieldname]", e.getMessage());
|
assertEquals("unexpected fieldname [bad_fieldname]", e.getMessage());
|
||||||
|
@ -253,7 +254,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("cannot parse object with name [bad_fieldname]", e.getMessage());
|
assertEquals("cannot parse object with name [bad_fieldname]", e.getMessage());
|
||||||
|
@ -270,7 +271,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("expected a parsing exception");
|
fail("expected a parsing exception");
|
||||||
} catch (ParsingException e) {
|
} catch (ParsingException e) {
|
||||||
assertEquals("cannot parse object with name [bad_fieldname]", e.getMessage());
|
assertEquals("cannot parse object with name [bad_fieldname]", e.getMessage());
|
||||||
|
@ -354,7 +355,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
XContentParser parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
XContentParser parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
HighlightBuilder highlightBuilder = HighlightBuilder.fromXContent(context);
|
HighlightBuilder highlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
assertArrayEquals("setting tags_schema 'styled' should alter pre_tags", HighlightBuilder.DEFAULT_STYLED_PRE_TAG,
|
assertArrayEquals("setting tags_schema 'styled' should alter pre_tags", HighlightBuilder.DEFAULT_STYLED_PRE_TAG,
|
||||||
highlightBuilder.preTags());
|
highlightBuilder.preTags());
|
||||||
assertArrayEquals("setting tags_schema 'styled' should alter post_tags", HighlightBuilder.DEFAULT_STYLED_POST_TAGS,
|
assertArrayEquals("setting tags_schema 'styled' should alter post_tags", HighlightBuilder.DEFAULT_STYLED_POST_TAGS,
|
||||||
|
@ -366,7 +367,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
highlightBuilder = HighlightBuilder.fromXContent(context);
|
highlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
assertArrayEquals("setting tags_schema 'default' should alter pre_tags", HighlightBuilder.DEFAULT_PRE_TAGS,
|
assertArrayEquals("setting tags_schema 'default' should alter pre_tags", HighlightBuilder.DEFAULT_PRE_TAGS,
|
||||||
highlightBuilder.preTags());
|
highlightBuilder.preTags());
|
||||||
assertArrayEquals("setting tags_schema 'default' should alter post_tags", HighlightBuilder.DEFAULT_POST_TAGS,
|
assertArrayEquals("setting tags_schema 'default' should alter post_tags", HighlightBuilder.DEFAULT_POST_TAGS,
|
||||||
|
@ -379,13 +380,42 @@ public class HighlightBuilderTests extends ESTestCase {
|
||||||
|
|
||||||
context.reset(parser);
|
context.reset(parser);
|
||||||
try {
|
try {
|
||||||
highlightBuilder = HighlightBuilder.fromXContent(context);
|
HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
fail("setting unknown tag schema should throw exception");
|
fail("setting unknown tag schema should throw exception");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
assertEquals("Unknown tag schema [somthing_else]", e.getMessage());
|
assertEquals("Unknown tag schema [somthing_else]", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test parsing empty highlight or empty fields blocks
|
||||||
|
*/
|
||||||
|
public void testParsingEmptyStructure() throws IOException {
|
||||||
|
QueryParseContext context = new QueryParseContext(indicesQueriesRegistry);
|
||||||
|
context.parseFieldMatcher(new ParseFieldMatcher(Settings.EMPTY));
|
||||||
|
String highlightElement = "{ }";
|
||||||
|
XContentParser parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
||||||
|
|
||||||
|
context.reset(parser);
|
||||||
|
HighlightBuilder highlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
|
assertEquals("expected plain HighlightBuilder", new HighlightBuilder(), highlightBuilder);
|
||||||
|
|
||||||
|
highlightElement = "{ \"fields\" : { } }";
|
||||||
|
parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
||||||
|
|
||||||
|
context.reset(parser);
|
||||||
|
highlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
|
assertEquals("defining no field should return plain HighlightBuilder", new HighlightBuilder(), highlightBuilder);
|
||||||
|
|
||||||
|
highlightElement = "{ \"fields\" : { \"foo\" : { } } }";
|
||||||
|
parser = XContentFactory.xContent(highlightElement).createParser(highlightElement);
|
||||||
|
|
||||||
|
context.reset(parser);
|
||||||
|
highlightBuilder = HighlightBuilder.PROTOTYPE.fromXContent(context);
|
||||||
|
assertEquals("expected HighlightBuilder with field", new HighlightBuilder().field(new Field("foo")), highlightBuilder);
|
||||||
|
System.out.println(Math.log(1/(double)(1+1)) + 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
protected static XContentBuilder toXContent(HighlightBuilder highlight, XContentType contentType) throws IOException {
|
protected static XContentBuilder toXContent(HighlightBuilder highlight, XContentType contentType) throws IOException {
|
||||||
XContentBuilder builder = XContentFactory.contentBuilder(contentType);
|
XContentBuilder builder = XContentFactory.contentBuilder(contentType);
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
|
|
Loading…
Reference in New Issue