Add highlighter type switch
This commit is contained in:
parent
4573abc737
commit
c551f93cae
|
@ -646,6 +646,14 @@ public class SearchRequestBuilder extends ActionRequestBuilder<SearchRequest, Se
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The highlighter type to use.
|
||||
*/
|
||||
public SearchRequestBuilder setHighlighterType(String type) {
|
||||
highlightBuilder().highlighterType(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source of the request as a json string. Note, settings anything other
|
||||
* than the search type will cause this source to be overridden, consider using
|
||||
|
|
|
@ -48,6 +48,9 @@ public class HighlightBuilder implements ToXContent {
|
|||
|
||||
private Boolean requireFieldMatch;
|
||||
|
||||
private String highlighterType;
|
||||
|
||||
|
||||
/**
|
||||
* Adds a field to be highlighted with default fragment size of 100 characters, and
|
||||
* default number of fragments of 5 using the default encoder
|
||||
|
@ -176,6 +179,15 @@ public class HighlightBuilder implements ToXContent {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type of highlighter to use. Supported types
|
||||
* are <tt>highlighter</tt> and <tt>fast-vector-highlighter</tt>.
|
||||
*/
|
||||
public HighlightBuilder highlighterType(String highlighterType) {
|
||||
this.highlighterType = highlighterType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject("highlight");
|
||||
|
@ -197,6 +209,9 @@ public class HighlightBuilder implements ToXContent {
|
|||
if (requireFieldMatch != null) {
|
||||
builder.field("require_field_match", requireFieldMatch);
|
||||
}
|
||||
if (highlighterType != null) {
|
||||
builder.field("type", highlighterType);
|
||||
}
|
||||
if (fields != null) {
|
||||
builder.startObject("fields");
|
||||
for (Field field : fields) {
|
||||
|
@ -213,6 +228,9 @@ public class HighlightBuilder implements ToXContent {
|
|||
if (field.requireFieldMatch != null) {
|
||||
builder.field("require_field_match", field.requireFieldMatch);
|
||||
}
|
||||
if (field.highlighterType != null) {
|
||||
builder.field("type", field.highlighterType);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
}
|
||||
|
@ -229,6 +247,7 @@ public class HighlightBuilder implements ToXContent {
|
|||
int fragmentOffset = -1;
|
||||
int numOfFragments = -1;
|
||||
Boolean requireFieldMatch;
|
||||
String highlighterType;
|
||||
|
||||
public Field(String name) {
|
||||
this.name = name;
|
||||
|
@ -257,5 +276,10 @@ public class HighlightBuilder implements ToXContent {
|
|||
this.requireFieldMatch = requireFieldMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Field highlighterType(String highlighterType) {
|
||||
this.highlighterType = highlighterType;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,10 +129,22 @@ public class HighlightPhase extends AbstractComponent implements FetchSubPhase {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if we can do highlighting using Term Vectors, use FastVectorHighlighter, otherwise, use the
|
||||
// slower plain highlighter
|
||||
if (mapper.termVector() != Field.TermVector.WITH_POSITIONS_OFFSETS) {
|
||||
boolean useFastVectorHighlighter;
|
||||
if (field.highlighterType() == null) {
|
||||
// if we can do highlighting using Term Vectors, use FastVectorHighlighter, otherwise, use the
|
||||
// slower plain highlighter
|
||||
useFastVectorHighlighter = mapper.termVector() == Field.TermVector.WITH_POSITIONS_OFFSETS;
|
||||
} else if (field.highlighterType().equals("fast-vector-highlighter")) {
|
||||
if (mapper.termVector() != Field.TermVector.WITH_POSITIONS_OFFSETS) {
|
||||
throw new FetchPhaseExecutionException(context, "The field [" + field.field() + "] should be indexed with term vector with position offsets to be used with fast vector highlighter");
|
||||
}
|
||||
useFastVectorHighlighter = true;
|
||||
} else if (field.highlighterType().equals("highlighter")) {
|
||||
useFastVectorHighlighter = false;
|
||||
} else {
|
||||
throw new FetchPhaseExecutionException(context, "Unknown highlighter type [" + field.highlighterType() + "] for the field [" + field.field() + "]");
|
||||
}
|
||||
if (!useFastVectorHighlighter) {
|
||||
MapperHighlightEntry entry = cache.mappers.get(mapper);
|
||||
if (entry == null) {
|
||||
// Don't use the context.query() since it might be rewritten, and we need to pass the non rewritten queries to
|
||||
|
|
|
@ -76,6 +76,7 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
String globalEncoder = "default";
|
||||
int globalBoundaryMaxScan = SimpleBoundaryScanner2.DEFAULT_MAX_SCAN;
|
||||
char[] globalBoundaryChars = SimpleBoundaryScanner2.DEFAULT_BOUNDARY_CHARS;
|
||||
String globalHighlighterType = null;
|
||||
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -117,6 +118,8 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
globalBoundaryMaxScan = parser.intValue();
|
||||
} else if ("boundary_chars".equals(topLevelFieldName) || "boundaryChars".equals(topLevelFieldName)) {
|
||||
globalBoundaryChars = parser.text().toCharArray();
|
||||
} else if ("type".equals(topLevelFieldName)) {
|
||||
globalHighlighterType = parser.text();
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("fields".equals(topLevelFieldName)) {
|
||||
|
@ -161,6 +164,8 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
field.boundaryMaxScan(parser.intValue());
|
||||
} else if ("boundary_chars".equals(topLevelFieldName) || "boundaryChars".equals(topLevelFieldName)) {
|
||||
field.boundaryChars(parser.text().toCharArray());
|
||||
} else if ("type".equals(fieldName)) {
|
||||
field.highlighterType(parser.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,6 +211,9 @@ public class HighlighterParseElement implements SearchParseElement {
|
|||
if (field.boundaryChars() == null) {
|
||||
field.boundaryChars(globalBoundaryChars);
|
||||
}
|
||||
if (field.highlighterType() == null) {
|
||||
field.highlighterType(globalHighlighterType);
|
||||
}
|
||||
}
|
||||
|
||||
context.highlight(new SearchContextHighlight(fields));
|
||||
|
|
|
@ -58,6 +58,8 @@ public class SearchContextHighlight {
|
|||
|
||||
private Boolean requireFieldMatch;
|
||||
|
||||
private String highlighterType;
|
||||
|
||||
private int boundaryMaxScan = -1;
|
||||
private char[] boundaryChars = null;
|
||||
|
||||
|
@ -141,6 +143,14 @@ public class SearchContextHighlight {
|
|||
this.requireFieldMatch = requireFieldMatch;
|
||||
}
|
||||
|
||||
public String highlighterType() {
|
||||
return highlighterType;
|
||||
}
|
||||
|
||||
public void highlighterType(String type) {
|
||||
this.highlighterType = type;
|
||||
}
|
||||
|
||||
public int boundaryMaxScan() {
|
||||
return boundaryMaxScan;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.indices.IndexMissingException;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
@ -781,4 +782,109 @@ public class HighlighterSearchTests extends AbstractNodesTests {
|
|||
hit = search.hits().getAt(0);
|
||||
assertThat(hit.highlightFields().get("title.key").fragments()[0].string(), equalTo("<em>this</em> <em>is</em> <em>a</em> <em>test</em>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFastVectorHighlighterShouldFailIfNoTermVectors() throws Exception {
|
||||
try {
|
||||
client.admin().indices().prepareDelete("test").execute().actionGet();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 2))
|
||||
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties")
|
||||
.startObject("title").field("type", "string").field("store", "yes").field("term_vector", "no").endObject()
|
||||
.endObject().endObject().endObject())
|
||||
.execute().actionGet();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
client.prepareIndex("test", "type1", Integer.toString(i))
|
||||
.setSource("title", "This is a test for the enabling fast vector highlighter").setRefresh(true).execute().actionGet();
|
||||
}
|
||||
|
||||
SearchResponse search = client.prepareSearch()
|
||||
.setQuery(matchPhraseQuery("title", "this is a test"))
|
||||
.addHighlightedField("title", 50, 1, 10)
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat(Arrays.toString(search.shardFailures()), search.failedShards(), equalTo(0));
|
||||
|
||||
search = client.prepareSearch()
|
||||
.setQuery(matchPhraseQuery("title", "this is a test"))
|
||||
.addHighlightedField("title", 50, 1, 10)
|
||||
.setHighlighterType("fast-vector-highlighter")
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat(search.failedShards(), equalTo(2));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableFastVectorHighlighter() throws Exception {
|
||||
try {
|
||||
client.admin().indices().prepareDelete("test").execute().actionGet();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 2))
|
||||
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties")
|
||||
.startObject("title").field("type", "string").field("store", "yes").field("term_vector", "with_positions_offsets").endObject()
|
||||
.endObject().endObject().endObject())
|
||||
.execute().actionGet();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
client.prepareIndex("test", "type1", Integer.toString(i))
|
||||
.setSource("title", "This is a test for the workaround for the fast vector highlighting SOLR-3724").setRefresh(true).execute().actionGet();
|
||||
}
|
||||
|
||||
SearchResponse search = client.prepareSearch()
|
||||
.setQuery(matchPhraseQuery("title", "test for the workaround"))
|
||||
.addHighlightedField("title", 50, 1, 10)
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat(Arrays.toString(search.shardFailures()), search.failedShards(), equalTo(0));
|
||||
|
||||
assertThat(search.hits().totalHits(), equalTo(5l));
|
||||
assertThat(search.hits().hits().length, equalTo(5));
|
||||
|
||||
for (SearchHit hit : search.hits()) {
|
||||
// Because of SOLR-3724 nothing is highlighted when FVH is used
|
||||
assertThat(hit.highlightFields().isEmpty(), equalTo(true));
|
||||
}
|
||||
|
||||
// Using plain highlighter instead of FVH
|
||||
search = client.prepareSearch()
|
||||
.setQuery(matchPhraseQuery("title", "test for the workaround"))
|
||||
.addHighlightedField("title", 50, 1, 10)
|
||||
.setHighlighterType("highlighter")
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat(Arrays.toString(search.shardFailures()), search.failedShards(), equalTo(0));
|
||||
|
||||
assertThat(search.hits().totalHits(), equalTo(5l));
|
||||
assertThat(search.hits().hits().length, equalTo(5));
|
||||
|
||||
for (SearchHit hit : search.hits()) {
|
||||
// With plain highlighter terms are highlighted correctly
|
||||
assertThat(hit.highlightFields().get("title").fragments()[0].string(), equalTo("This is a <em>test</em> for the <em>workaround</em> for the fast vector highlighting SOLR-3724"));
|
||||
}
|
||||
|
||||
// Using plain highlighter instead of FVH on the field level
|
||||
search = client.prepareSearch()
|
||||
.setQuery(matchPhraseQuery("title", "test for the workaround"))
|
||||
.addHighlightedField(new HighlightBuilder.Field("title").highlighterType("highlighter"))
|
||||
.setHighlighterType("highlighter")
|
||||
.execute().actionGet();
|
||||
|
||||
assertThat(Arrays.toString(search.shardFailures()), search.failedShards(), equalTo(0));
|
||||
|
||||
assertThat(search.hits().totalHits(), equalTo(5l));
|
||||
assertThat(search.hits().hits().length, equalTo(5));
|
||||
|
||||
for (SearchHit hit : search.hits()) {
|
||||
// With plain highlighter terms are highlighted correctly
|
||||
assertThat(hit.highlightFields().get("title").fragments()[0].string(), equalTo("This is a <em>test</em> for the <em>workaround</em> for the fast vector highlighting SOLR-3724"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue