diff --git a/.idea/libraries/lucene.xml b/.idea/libraries/lucene.xml
index 56983e7ebc1..e06be2d49d6 100644
--- a/.idea/libraries/lucene.xml
+++ b/.idea/libraries/lucene.xml
@@ -5,6 +5,8 @@
+
+
@@ -12,6 +14,8 @@
+
+
\ No newline at end of file
diff --git a/modules/elasticsearch/build.gradle b/modules/elasticsearch/build.gradle
index f30e0fac531..a83a5235683 100644
--- a/modules/elasticsearch/build.gradle
+++ b/modules/elasticsearch/build.gradle
@@ -41,6 +41,8 @@ dependencies {
compile 'org.apache.lucene:lucene-analyzers:3.0.3'
compile 'org.apache.lucene:lucene-queries:3.0.3'
compile 'org.apache.lucene:lucene-fast-vector-highlighter:3.0.3'
+ compile 'org.apache.lucene:lucene-memory:3.0.3'
+ compile 'org.apache.lucene:lucene-highlighter:3.0.3'
}
configurations {
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java
index 318f4402e66..f86eadfb332 100644
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java
@@ -19,11 +19,20 @@
package org.elasticsearch.search.highlight;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.highlight.*;
+import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.vectorhighlight.*;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.common.collect.ImmutableMap;
+import org.elasticsearch.common.io.FastStringReader;
+import org.elasticsearch.common.lucene.document.SingleFieldSelector;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.Uid;
@@ -35,9 +44,10 @@ import org.elasticsearch.search.highlight.vectorhighlight.SourceScoreOrderFragme
import org.elasticsearch.search.highlight.vectorhighlight.SourceSimpleFragmentsBuilder;
import org.elasticsearch.search.internal.InternalSearchHit;
import org.elasticsearch.search.internal.SearchContext;
+import org.elasticsearch.search.lookup.SearchLookup;
import java.io.IOException;
-import java.util.Map;
+import java.util.*;
import static org.elasticsearch.common.collect.Maps.*;
@@ -46,6 +56,8 @@ import static org.elasticsearch.common.collect.Maps.*;
*/
public class HighlightPhase implements SearchHitPhase {
+ private static final Encoder DEFAULT_ENCODER = new DefaultEncoder();
+
@Override public Map parseElements() {
return ImmutableMap.of("highlight", new HighlighterParseElement());
}
@@ -65,19 +77,91 @@ public class HighlightPhase implements SearchHitPhase {
throw new SearchException(context.shardTarget(), "No mapping found for [" + field.field() + "]");
}
- FastVectorHighlighter highlighter = buildHighlighter(context, mapper, field);
- FieldQuery fieldQuery = buildFieldQuery(highlighter, context.query(), reader, field);
+ // if we can do highlighting using Term Vectors, use FastVectorHighlighter, otherwise, use the
+ // slower plain highlighter
+ if (mapper.termVector() != Field.TermVector.WITH_POSITIONS_OFFSETS) {
+ if (!context.queryRewritten()) {
+ try {
+ context.updateRewriteQuery(context.searcher().rewrite(context.query()));
+ } catch (IOException e) {
+ throw new FetchPhaseExecutionException(context, "Failed to highlight field [" + field.field() + "]", e);
+ }
+ }
+ // Don't use the context.query() since it might be rewritten, and we need to pass the non rewritten queries to
+ // let the highlighter handle MultiTerm ones
+ QueryScorer queryScorer = new QueryScorer(context.parsedQuery().query(), null);
+ queryScorer.setExpandMultiTermQuery(true);
+ Fragmenter fragmenter;
+ if (field.numberOfFragments() == 0) {
+ fragmenter = new NullFragmenter();
+ } else {
+ fragmenter = new SimpleSpanFragmenter(queryScorer, field.fragmentCharSize());
+ }
+ Formatter formatter = new SimpleHTMLFormatter(field.preTags()[0], field.postTags()[0]);
+ Highlighter highlighter = new Highlighter(formatter, DEFAULT_ENCODER, queryScorer);
+ highlighter.setTextFragmenter(fragmenter);
- String[] fragments;
- try {
- // a HACK to make highlighter do highlighting, even though its using the single frag list builder
- int numberOfFragments = field.numberOfFragments() == 0 ? 1 : field.numberOfFragments();
- fragments = highlighter.getBestFragments(fieldQuery, context.searcher().getIndexReader(), docId, mapper.names().indexName(), field.fragmentCharSize(), numberOfFragments);
- } catch (IOException e) {
- throw new FetchPhaseExecutionException(context, "Failed to highlight field [" + field.field() + "]", e);
+ List