Make HighlightBuilder produce SearchContextHighlight
The HighlightBuilder should be able to procude a SeachContextHighlight object which contains the merged global and field options, also contains objects that can only be created on the index shard (like the actual lucene Query object used during highlighting). This is done by the build() method of the HighlighBuilder. Also adding tests that make sure the produced SearchContextHighlighter is similar to the one we would get when parsing the xContent directly with the current HighlightParseElement.
This commit is contained in:
parent
20bff773ed
commit
cb84b1ff1a
|
@ -125,7 +125,7 @@ public abstract class AbstractHighlighterBuilder<HB extends AbstractHighlighterB
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the fragment size in characters, defaults to {@link HighlighterParseElement#DEFAULT_FRAGMENT_CHAR_SIZE}
|
||||
* Set the fragment size in characters, defaults to {@link HighlightBuilder#DEFAULT_FRAGMENT_CHAR_SIZE}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public HB fragmentSize(Integer fragmentSize) {
|
||||
|
@ -141,7 +141,7 @@ public abstract class AbstractHighlighterBuilder<HB extends AbstractHighlighterB
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the number of fragments, defaults to {@link HighlighterParseElement#DEFAULT_NUMBER_OF_FRAGMENTS}
|
||||
* Set the number of fragments, defaults to {@link HighlightBuilder#DEFAULT_NUMBER_OF_FRAGMENTS}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public HB numOfFragments(Integer numOfFragments) {
|
||||
|
@ -428,7 +428,7 @@ public abstract class AbstractHighlighterBuilder<HB extends AbstractHighlighterB
|
|||
}
|
||||
|
||||
/**
|
||||
* internal hashCode calculation to overwrite for the implementing classes.
|
||||
* fields only present in subclass should contribute to hashCode in the implementation
|
||||
*/
|
||||
protected abstract int doHashCode();
|
||||
|
||||
|
@ -462,7 +462,7 @@ public abstract class AbstractHighlighterBuilder<HB extends AbstractHighlighterB
|
|||
}
|
||||
|
||||
/**
|
||||
* internal equals to overwrite for the implementing classes.
|
||||
* fields only present in subclass should be checked for equality in the implementation
|
||||
*/
|
||||
protected abstract boolean doEquals(HB other);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.elasticsearch.search.highlight;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.vectorhighlight.SimpleBoundaryScanner;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -28,13 +30,23 @@ import org.elasticsearch.common.xcontent.ToXContent;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.search.SearchParseException;
|
||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions.Builder;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A builder for search highlighting. Settings can control how large fields
|
||||
|
@ -48,6 +60,51 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
|||
|
||||
public static final String HIGHLIGHT_ELEMENT_NAME = "highlight";
|
||||
|
||||
/** default for whether to highlight fields based on the source even if stored separately */
|
||||
public static final boolean DEFAULT_FORCE_SOURCE = false;
|
||||
/** default for whether a field should be highlighted only if a query matches that field */
|
||||
public static final boolean DEFAULT_REQUIRE_FIELD_MATCH = true;
|
||||
/** default for whether <tt>fvh</tt> should provide highlighting on filter clauses */
|
||||
public static final boolean DEFAULT_HIGHLIGHT_FILTER = false;
|
||||
/** default for highlight fragments being ordered by score */
|
||||
public static final boolean DEFAULT_SCORE_ORDERED = false;
|
||||
/** the default encoder setting */
|
||||
public static final String DEFAULT_ENCODER = "default";
|
||||
/** default for the maximum number of phrases the fvh will consider */
|
||||
public static final int DEFAULT_PHRASE_LIMIT = 256;
|
||||
/** default for fragment size when there are no matches */
|
||||
public static final int DEFAULT_NO_MATCH_SIZE = 0;
|
||||
/** the default number of fragments for highlighting */
|
||||
public static final int DEFAULT_NUMBER_OF_FRAGMENTS = 5;
|
||||
/** the default number of fragments size in characters */
|
||||
public static final int DEFAULT_FRAGMENT_CHAR_SIZE = 100;
|
||||
/** the default opening tag */
|
||||
public static final String[] DEFAULT_PRE_TAGS = new String[]{"<em>"};
|
||||
/** the default closing tag */
|
||||
public static final String[] DEFAULT_POST_TAGS = new String[]{"</em>"};
|
||||
|
||||
/** the default opening tags when <tt>tag_schema = "styled"</tt> */
|
||||
public static final String[] STYLED_PRE_TAG = {
|
||||
"<em class=\"hlt1\">", "<em class=\"hlt2\">", "<em class=\"hlt3\">",
|
||||
"<em class=\"hlt4\">", "<em class=\"hlt5\">", "<em class=\"hlt6\">",
|
||||
"<em class=\"hlt7\">", "<em class=\"hlt8\">", "<em class=\"hlt9\">",
|
||||
"<em class=\"hlt10\">"
|
||||
};
|
||||
/** the default closing tags when <tt>tag_schema = "styled"</tt> */
|
||||
public static final String[] STYLED_POST_TAGS = {"</em>"};
|
||||
|
||||
/**
|
||||
* a {@link FieldOptions.Builder} with default settings
|
||||
*/
|
||||
public final static Builder defaultFieldOptions() {
|
||||
return new SearchContextHighlight.FieldOptions.Builder()
|
||||
.preTags(DEFAULT_PRE_TAGS).postTags(DEFAULT_POST_TAGS).scoreOrdered(DEFAULT_SCORE_ORDERED).highlightFilter(DEFAULT_HIGHLIGHT_FILTER)
|
||||
.requireFieldMatch(DEFAULT_REQUIRE_FIELD_MATCH).forceSource(DEFAULT_FORCE_SOURCE).fragmentCharSize(DEFAULT_FRAGMENT_CHAR_SIZE).numberOfFragments(DEFAULT_NUMBER_OF_FRAGMENTS)
|
||||
.encoder(DEFAULT_ENCODER).boundaryMaxScan(SimpleBoundaryScanner.DEFAULT_MAX_SCAN)
|
||||
.boundaryChars(SimpleBoundaryScanner.DEFAULT_BOUNDARY_CHARS)
|
||||
.noMatchSize(DEFAULT_NO_MATCH_SIZE).phraseLimit(DEFAULT_PHRASE_LIMIT);
|
||||
}
|
||||
|
||||
private final List<Field> fields = new ArrayList<>();
|
||||
|
||||
private String encoder;
|
||||
|
@ -120,12 +177,12 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
|||
public HighlightBuilder tagsSchema(String schemaName) {
|
||||
switch (schemaName) {
|
||||
case "default":
|
||||
preTags(HighlighterParseElement.DEFAULT_PRE_TAGS);
|
||||
postTags(HighlighterParseElement.DEFAULT_POST_TAGS);
|
||||
preTags(DEFAULT_PRE_TAGS);
|
||||
postTags(DEFAULT_POST_TAGS);
|
||||
break;
|
||||
case "styled":
|
||||
preTags(HighlighterParseElement.STYLED_PRE_TAG);
|
||||
postTags(HighlighterParseElement.STYLED_POST_TAGS);
|
||||
preTags(STYLED_PRE_TAG);
|
||||
postTags(STYLED_POST_TAGS);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown tag schema ["+ schemaName +"]");
|
||||
|
@ -289,7 +346,95 @@ public class HighlightBuilder extends AbstractHighlighterBuilder<HighlightBuilde
|
|||
return highlightBuilder;
|
||||
}
|
||||
|
||||
public void parse(XContentParser parser, SearchContext context) throws Exception {
|
||||
try {
|
||||
context.highlight(build(context.indexShard().getQueryShardContext()));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new SearchParseException(context, "Error while trying to parse Highlighter element in request", parser.getTokenLocation());
|
||||
}
|
||||
}
|
||||
|
||||
SearchContextHighlight build(QueryShardContext context) throws IOException {
|
||||
// create template global options that are later merged with any partial field options
|
||||
final SearchContextHighlight.FieldOptions.Builder globalOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder();
|
||||
globalOptionsBuilder.encoder(this.encoder);
|
||||
transferOptions(this, globalOptionsBuilder, context);
|
||||
|
||||
// overwrite unset global options by default values
|
||||
globalOptionsBuilder.merge(defaultFieldOptions().build());
|
||||
|
||||
// create field options
|
||||
Collection<org.elasticsearch.search.highlight.SearchContextHighlight.Field> fieldOptions = new ArrayList<>();
|
||||
for (Field field : this.fields) {
|
||||
final SearchContextHighlight.FieldOptions.Builder fieldOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder();
|
||||
fieldOptionsBuilder.fragmentOffset(field.fragmentOffset);
|
||||
if (field.matchedFields != null) {
|
||||
Set<String> matchedFields = new HashSet<String>(field.matchedFields.length);
|
||||
Collections.addAll(matchedFields, field.matchedFields);
|
||||
fieldOptionsBuilder.matchedFields(matchedFields);
|
||||
}
|
||||
transferOptions(field, fieldOptionsBuilder, context);
|
||||
fieldOptions.add(new SearchContextHighlight.Field(field.name(), fieldOptionsBuilder.merge(globalOptionsBuilder.build()).build()));
|
||||
}
|
||||
return new SearchContextHighlight(fieldOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers field options present in the input {@link AbstractHighlighterBuilder} to the receiving
|
||||
* {@link FieldOptions.Builder}, effectively overwriting existing settings
|
||||
* @param targetOptionsBuilder the receiving options builder
|
||||
* @param highlighterBuilder highlight builder with the input options
|
||||
* @param context needed to convert {@link QueryBuilder} to {@link Query}
|
||||
* @throws IOException on errors parsing any optional nested highlight query
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static void transferOptions(AbstractHighlighterBuilder highlighterBuilder, SearchContextHighlight.FieldOptions.Builder targetOptionsBuilder, QueryShardContext context) throws IOException {
|
||||
targetOptionsBuilder.preTags(highlighterBuilder.preTags);
|
||||
targetOptionsBuilder.postTags(highlighterBuilder.postTags);
|
||||
targetOptionsBuilder.scoreOrdered("score".equals(highlighterBuilder.order));
|
||||
if (highlighterBuilder.highlightFilter != null) {
|
||||
targetOptionsBuilder.highlightFilter(highlighterBuilder.highlightFilter);
|
||||
}
|
||||
if (highlighterBuilder.fragmentSize != null) {
|
||||
targetOptionsBuilder.fragmentCharSize(highlighterBuilder.fragmentSize);
|
||||
}
|
||||
if (highlighterBuilder.numOfFragments != null) {
|
||||
targetOptionsBuilder.numberOfFragments(highlighterBuilder.numOfFragments);
|
||||
}
|
||||
if (highlighterBuilder.requireFieldMatch != null) {
|
||||
targetOptionsBuilder.requireFieldMatch(highlighterBuilder.requireFieldMatch);
|
||||
}
|
||||
if (highlighterBuilder.boundaryMaxScan != null) {
|
||||
targetOptionsBuilder.boundaryMaxScan(highlighterBuilder.boundaryMaxScan);
|
||||
}
|
||||
targetOptionsBuilder.boundaryChars(convertCharArray(highlighterBuilder.boundaryChars));
|
||||
targetOptionsBuilder.highlighterType(highlighterBuilder.highlighterType);
|
||||
targetOptionsBuilder.fragmenter(highlighterBuilder.fragmenter);
|
||||
if (highlighterBuilder.noMatchSize != null) {
|
||||
targetOptionsBuilder.noMatchSize(highlighterBuilder.noMatchSize);
|
||||
}
|
||||
if (highlighterBuilder.forceSource != null) {
|
||||
targetOptionsBuilder.forceSource(highlighterBuilder.forceSource);
|
||||
}
|
||||
if (highlighterBuilder.phraseLimit != null) {
|
||||
targetOptionsBuilder.phraseLimit(highlighterBuilder.phraseLimit);
|
||||
}
|
||||
targetOptionsBuilder.options(highlighterBuilder.options);
|
||||
if (highlighterBuilder.highlightQuery != null) {
|
||||
targetOptionsBuilder.highlightQuery(highlighterBuilder.highlightQuery.toQuery(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static Character[] convertCharArray(char[] array) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
Character[] charArray = new Character[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
charArray[i] = array[i];
|
||||
}
|
||||
return charArray;
|
||||
}
|
||||
|
||||
public void innerXContent(XContentBuilder builder) throws IOException {
|
||||
// first write common options
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.search.highlight;
|
||||
|
||||
import org.apache.lucene.search.vectorhighlight.SimpleBoundaryScanner;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
|
@ -52,39 +51,6 @@ import java.util.Set;
|
|||
*/
|
||||
public class HighlighterParseElement implements SearchParseElement {
|
||||
|
||||
/** default for whether to highlight fields based on the source even if stored separately */
|
||||
public static final boolean DEFAULT_FORCE_SOURCE = false;
|
||||
/** default for whether a field should be highlighted only if a query matches that field */
|
||||
public static final boolean DEFAULT_REQUIRE_FIELD_MATCH = true;
|
||||
/** default for whether <tt>fvh</tt> should provide highlighting on filter clauses */
|
||||
public static final boolean DEFAULT_HIGHLIGHT_FILTER = false;
|
||||
/** default for highlight fragments being ordered by score */
|
||||
public static final boolean DEFAULT_SCORE_ORDERED = false;
|
||||
/** the default encoder setting */
|
||||
public static final String DEFAULT_ENCODER = "default";
|
||||
/** default for the maximum number of phrases the fvh will consider */
|
||||
public static final int DEFAULT_PHRASE_LIMIT = 256;
|
||||
/** default for fragment size when there are no matches */
|
||||
public static final int DEFAULT_NO_MATCH_SIZE = 0;
|
||||
/** the default number of fragments for highlighting */
|
||||
public static final int DEFAULT_NUMBER_OF_FRAGMENTS = 5;
|
||||
/** the default number of fragments size in characters */
|
||||
public static final int DEFAULT_FRAGMENT_CHAR_SIZE = 100;
|
||||
/** the default opening tag */
|
||||
public static final String[] DEFAULT_PRE_TAGS = new String[]{"<em>"};
|
||||
/** the default closing tag */
|
||||
public static final String[] DEFAULT_POST_TAGS = new String[]{"</em>"};
|
||||
|
||||
/** the default opening tags when <tt>tag_schema = "styled"</tt> */
|
||||
public static final String[] STYLED_PRE_TAG = {
|
||||
"<em class=\"hlt1\">", "<em class=\"hlt2\">", "<em class=\"hlt3\">",
|
||||
"<em class=\"hlt4\">", "<em class=\"hlt5\">", "<em class=\"hlt6\">",
|
||||
"<em class=\"hlt7\">", "<em class=\"hlt8\">", "<em class=\"hlt9\">",
|
||||
"<em class=\"hlt10\">"
|
||||
};
|
||||
/** the default closing tags when <tt>tag_schema = "styled"</tt> */
|
||||
public static final String[] STYLED_POST_TAGS = {"</em>"};
|
||||
|
||||
@Override
|
||||
public void parse(XContentParser parser, SearchContext context) throws Exception {
|
||||
try {
|
||||
|
@ -99,12 +65,7 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
String topLevelFieldName = null;
|
||||
final List<Tuple<String, SearchContextHighlight.FieldOptions.Builder>> fieldsOptions = new ArrayList<>();
|
||||
|
||||
final SearchContextHighlight.FieldOptions.Builder globalOptionsBuilder = new SearchContextHighlight.FieldOptions.Builder()
|
||||
.preTags(DEFAULT_PRE_TAGS).postTags(DEFAULT_POST_TAGS).scoreOrdered(DEFAULT_SCORE_ORDERED).highlightFilter(DEFAULT_HIGHLIGHT_FILTER)
|
||||
.requireFieldMatch(DEFAULT_REQUIRE_FIELD_MATCH).forceSource(DEFAULT_FORCE_SOURCE).fragmentCharSize(DEFAULT_FRAGMENT_CHAR_SIZE).numberOfFragments(DEFAULT_NUMBER_OF_FRAGMENTS)
|
||||
.encoder(DEFAULT_ENCODER).boundaryMaxScan(SimpleBoundaryScanner.DEFAULT_MAX_SCAN)
|
||||
.boundaryChars(SimpleBoundaryScanner.DEFAULT_BOUNDARY_CHARS)
|
||||
.noMatchSize(DEFAULT_NO_MATCH_SIZE).phraseLimit(DEFAULT_PHRASE_LIMIT);
|
||||
final SearchContextHighlight.FieldOptions.Builder globalOptionsBuilder = HighlightBuilder.defaultFieldOptions();
|
||||
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -147,8 +108,8 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
} else if ("tags_schema".equals(topLevelFieldName) || "tagsSchema".equals(topLevelFieldName)) {
|
||||
String schema = parser.text();
|
||||
if ("styled".equals(schema)) {
|
||||
globalOptionsBuilder.preTags(STYLED_PRE_TAG);
|
||||
globalOptionsBuilder.postTags(STYLED_POST_TAGS);
|
||||
globalOptionsBuilder.preTags(HighlightBuilder.STYLED_PRE_TAG);
|
||||
globalOptionsBuilder.postTags(HighlightBuilder.STYLED_POST_TAGS);
|
||||
}
|
||||
} else if ("highlight_filter".equals(topLevelFieldName) || "highlightFilter".equals(topLevelFieldName)) {
|
||||
globalOptionsBuilder.highlightFilter(parser.booleanValue());
|
||||
|
|
|
@ -53,6 +53,10 @@ public class SearchContextHighlight {
|
|||
this.globalForceSource = globalForceSource;
|
||||
}
|
||||
|
||||
boolean globalForceSource() {
|
||||
return this.globalForceSource;
|
||||
}
|
||||
|
||||
public boolean forceSource(Field field) {
|
||||
if (globalForceSource) {
|
||||
return true;
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.search.highlight;
|
|||
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
|
@ -32,18 +34,21 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.IdsQueryParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryParser;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
import org.elasticsearch.index.query.TermQueryParser;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder.Field;
|
||||
import org.elasticsearch.search.highlight.SearchContextHighlight.FieldOptions;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.IndexSettingsModule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
@ -51,6 +56,7 @@ import java.io.IOException;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -73,8 +79,6 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
@SuppressWarnings("rawtypes")
|
||||
Set<QueryParser> injectedQueryParsers = new HashSet<>();
|
||||
injectedQueryParsers.add(new MatchAllQueryParser());
|
||||
injectedQueryParsers.add(new IdsQueryParser());
|
||||
injectedQueryParsers.add(new TermQueryParser());
|
||||
indicesQueriesRegistry = new IndicesQueriesRegistry(Settings.settingsBuilder().build(), injectedQueryParsers, namedWriteableRegistry);
|
||||
}
|
||||
|
||||
|
@ -128,7 +132,7 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generic test that creates new highlighter from the test highlighter and checks both for equality
|
||||
* creates random highlighter, renders it to xContent and back to new instance that should be equal to original
|
||||
*/
|
||||
public void testFromXContent() throws IOException {
|
||||
QueryParseContext context = new QueryParseContext(indicesQueriesRegistry);
|
||||
|
@ -261,6 +265,63 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
} catch (ParsingException e) {
|
||||
assertEquals("cannot parse object with name [bad_fieldname]", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* test that build() outputs a {@link SearchContextHighlight} that is similar to the one
|
||||
* we would get when parsing the xContent the test highlight builder is rendering out
|
||||
*/
|
||||
public void testBuildSearchContextHighlight() throws IOException {
|
||||
Settings indexSettings = Settings.settingsBuilder()
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
Index index = new Index(randomAsciiOfLengthBetween(1, 10));
|
||||
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(index, indexSettings);
|
||||
// shard context will only need indicesQueriesRegistry for building Query objects nested in highlighter
|
||||
QueryShardContext mockShardContext = new QueryShardContext(idxSettings, null, null, null, null, null, null, indicesQueriesRegistry);
|
||||
|
||||
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
|
||||
HighlightBuilder highlightBuilder = randomHighlighterBuilder();
|
||||
SearchContextHighlight highlight = highlightBuilder.build(mockShardContext);
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
|
||||
if (randomBoolean()) {
|
||||
builder.prettyPrint();
|
||||
}
|
||||
builder.startObject();
|
||||
highlightBuilder.innerXContent(builder);
|
||||
builder.endObject();
|
||||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
|
||||
SearchContextHighlight parsedHighlight = new HighlighterParseElement().parse(parser, mockShardContext);
|
||||
assertNotSame(highlight, parsedHighlight);
|
||||
assertEquals(highlight.globalForceSource(), parsedHighlight.globalForceSource());
|
||||
assertEquals(highlight.fields().size(), parsedHighlight.fields().size());
|
||||
|
||||
Iterator<org.elasticsearch.search.highlight.SearchContextHighlight.Field> iterator = parsedHighlight.fields().iterator();
|
||||
for (org.elasticsearch.search.highlight.SearchContextHighlight.Field field : highlight.fields()) {
|
||||
org.elasticsearch.search.highlight.SearchContextHighlight.Field otherField = iterator.next();
|
||||
assertEquals(field.field(), otherField.field());
|
||||
FieldOptions options = field.fieldOptions();
|
||||
FieldOptions otherOptions = otherField.fieldOptions();
|
||||
assertArrayEquals(options.boundaryChars(), options.boundaryChars());
|
||||
assertEquals(options.boundaryMaxScan(), otherOptions.boundaryMaxScan());
|
||||
assertEquals(options.encoder(), otherOptions.encoder());
|
||||
assertEquals(options.fragmentCharSize(), otherOptions.fragmentCharSize());
|
||||
assertEquals(options.fragmenter(), otherOptions.fragmenter());
|
||||
assertEquals(options.fragmentOffset(), otherOptions.fragmentOffset());
|
||||
assertEquals(options.highlighterType(), otherOptions.highlighterType());
|
||||
assertEquals(options.highlightFilter(), otherOptions.highlightFilter());
|
||||
assertEquals(options.highlightQuery(), otherOptions.highlightQuery());
|
||||
assertEquals(options.matchedFields(), otherOptions.matchedFields());
|
||||
assertEquals(options.noMatchSize(), otherOptions.noMatchSize());
|
||||
assertEquals(options.numberOfFragments(), otherOptions.numberOfFragments());
|
||||
assertEquals(options.options(), otherOptions.options());
|
||||
assertEquals(options.phraseLimit(), otherOptions.phraseLimit());
|
||||
assertArrayEquals(options.preTags(), otherOptions.preTags());
|
||||
assertArrayEquals(options.postTags(), otherOptions.postTags());
|
||||
assertEquals(options.requireFieldMatch(), otherOptions.requireFieldMatch());
|
||||
assertEquals(options.scoreOrdered(), otherOptions.scoreOrdered());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -277,9 +338,9 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
|
||||
context.reset(parser);
|
||||
HighlightBuilder highlightBuilder = HighlightBuilder.fromXContent(context);
|
||||
assertArrayEquals("setting tags_schema 'styled' should alter pre_tags", HighlighterParseElement.STYLED_PRE_TAG,
|
||||
assertArrayEquals("setting tags_schema 'styled' should alter pre_tags", HighlightBuilder.STYLED_PRE_TAG,
|
||||
highlightBuilder.preTags());
|
||||
assertArrayEquals("setting tags_schema 'styled' should alter post_tags", HighlighterParseElement.STYLED_POST_TAGS,
|
||||
assertArrayEquals("setting tags_schema 'styled' should alter post_tags", HighlightBuilder.STYLED_POST_TAGS,
|
||||
highlightBuilder.postTags());
|
||||
|
||||
highlightElement = "{\n" +
|
||||
|
@ -289,9 +350,9 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
|
||||
context.reset(parser);
|
||||
highlightBuilder = HighlightBuilder.fromXContent(context);
|
||||
assertArrayEquals("setting tags_schema 'default' should alter pre_tags", HighlighterParseElement.DEFAULT_PRE_TAGS,
|
||||
assertArrayEquals("setting tags_schema 'default' should alter pre_tags", HighlightBuilder.DEFAULT_PRE_TAGS,
|
||||
highlightBuilder.preTags());
|
||||
assertArrayEquals("setting tags_schema 'default' should alter post_tags", HighlighterParseElement.DEFAULT_POST_TAGS,
|
||||
assertArrayEquals("setting tags_schema 'default' should alter post_tags", HighlightBuilder.DEFAULT_POST_TAGS,
|
||||
highlightBuilder.postTags());
|
||||
|
||||
highlightElement = "{\n" +
|
||||
|
@ -362,20 +423,9 @@ public class HighlightBuilderTests extends ESTestCase {
|
|||
highlightBuilder.fragmenter(randomAsciiOfLengthBetween(1, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
QueryBuilder highlightQuery;
|
||||
switch (randomInt(2)) {
|
||||
case 0:
|
||||
highlightQuery = new MatchAllQueryBuilder();
|
||||
break;
|
||||
case 1:
|
||||
highlightQuery = new IdsQueryBuilder();
|
||||
break;
|
||||
default:
|
||||
case 2:
|
||||
highlightQuery = new TermQueryBuilder(randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10));
|
||||
break;
|
||||
}
|
||||
QueryBuilder highlightQuery = new MatchAllQueryBuilder();
|
||||
highlightQuery.boost((float) randomDoubleBetween(0, 10, false));
|
||||
highlightQuery.queryName(randomAsciiOfLength(10));
|
||||
highlightBuilder.highlightQuery(highlightQuery);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
|
|
Loading…
Reference in New Issue