From 0ffce18e13e88ef21fed58b11074d708f89f523e Mon Sep 17 00:00:00 2001 From: David Wayne Smiley Date: Wed, 30 Jul 2014 16:27:13 +0000 Subject: [PATCH] SOLR-6281: Made PostingsSolrHighlighter more configurable git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1614702 13f79535-47bb-0310-9956-ffa450edef68 --- solr/CHANGES.txt | 2 + .../highlight/PostingsSolrHighlighter.java | 188 ++++++++++-------- 2 files changed, 103 insertions(+), 87 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 3c4d4d256c1..bf570657e3b 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -314,6 +314,8 @@ Other Changes * SOLR-6290: Harden and speed up CollectionsAPIAsyncDistributedZkTest. (Mark Miller, shalin) +* SOLR-6281: Made PostingsSolrHighlighter more configurable via subclass extension. (David Smiley) + ================== 4.9.0 ================== Versions of Major Components diff --git a/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java b/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java index ba90981a8bf..007ed7bbbc2 100644 --- a/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java +++ b/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java @@ -17,13 +17,6 @@ package org.apache.solr.highlight; * limitations under the License. */ -import java.io.IOException; -import java.text.BreakIterator; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.StoredDocument; import org.apache.lucene.search.Query; @@ -47,6 +40,13 @@ import org.apache.solr.search.DocList; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.util.plugin.PluginInfoInitialized; +import java.io.IOException; +import java.text.BreakIterator; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + /** * Highlighter impl that uses {@link PostingsHighlighter} *

@@ -119,88 +119,34 @@ public class PostingsSolrHighlighter extends SolrHighlighter implements PluginIn final SolrParams params = req.getParams(); // if highlighting isnt enabled, then why call doHighlighting? - if (isHighlightingEnabled(params)) { - SolrIndexSearcher searcher = req.getSearcher(); - int[] docIDs = toDocIDs(docs); - - // fetch the unique keys - String[] keys = getUniqueKeys(searcher, docIDs); - - // query-time parameters - int maxLength = params.getInt(HighlightParams.MAX_CHARS, PostingsHighlighter.DEFAULT_MAX_LENGTH); - String[] fieldNames = getHighlightFields(query, req, defaultFields); - - int maxPassages[] = new int[fieldNames.length]; - for (int i = 0; i < fieldNames.length; i++) { - maxPassages[i] = params.getFieldInt(fieldNames[i], HighlightParams.SNIPPETS, 1); - } - - final IndexSchema schema = req.getSchema(); - - PostingsHighlighter highlighter = new PostingsHighlighter(maxLength) { - @Override - protected Passage[] getEmptyHighlight(String fieldName, BreakIterator bi, int maxPassages) { - boolean defaultSummary = params.getFieldBool(fieldName, HighlightParams.DEFAULT_SUMMARY, true); - if (defaultSummary) { - return super.getEmptyHighlight(fieldName, bi, maxPassages); - } else { - return new Passage[0]; - } - } - - @Override - protected PassageFormatter getFormatter(String fieldName) { - String preTag = params.getFieldParam(fieldName, HighlightParams.TAG_PRE, ""); - String postTag = params.getFieldParam(fieldName, HighlightParams.TAG_POST, ""); - String ellipsis = params.getFieldParam(fieldName, HighlightParams.TAG_ELLIPSIS, "... "); - String encoder = params.getFieldParam(fieldName, HighlightParams.ENCODER, "simple"); - return new DefaultPassageFormatter(preTag, postTag, ellipsis, "html".equals(encoder)); - } - - @Override - protected PassageScorer getScorer(String fieldName) { - float k1 = params.getFieldFloat(fieldName, HighlightParams.SCORE_K1, 1.2f); - float b = params.getFieldFloat(fieldName, HighlightParams.SCORE_B, 0.75f); - float pivot = params.getFieldFloat(fieldName, HighlightParams.SCORE_PIVOT, 87f); - return new PassageScorer(k1, b, pivot); - } - - @Override - protected BreakIterator getBreakIterator(String field) { - String language = params.getFieldParam(field, HighlightParams.BS_LANGUAGE); - String country = params.getFieldParam(field, HighlightParams.BS_COUNTRY); - String variant = params.getFieldParam(field, HighlightParams.BS_VARIANT); - Locale locale = parseLocale(language, country, variant); - String type = params.getFieldParam(field, HighlightParams.BS_TYPE); - return parseBreakIterator(type, locale); - } - - @Override - protected char getMultiValuedSeparator(String field) { - String sep = params.getFieldParam(field, HighlightParams.MULTI_VALUED_SEPARATOR, " "); - if (sep.length() != 1) { - throw new IllegalArgumentException(HighlightParams.MULTI_VALUED_SEPARATOR + " must be exactly one character."); - } - return sep.charAt(0); - } - - @Override - protected Analyzer getIndexAnalyzer(String field) { - if (params.getFieldBool(field, HighlightParams.HIGHLIGHT_MULTI_TERM, false)) { - return schema.getIndexAnalyzer(); - } else { - return null; - } - } - }; - - Map snippets = highlighter.highlightFields(fieldNames, query, searcher, docIDs, maxPassages); - return encodeSnippets(keys, fieldNames, snippets); - } else { + if (!isHighlightingEnabled(params)) return null; + + SolrIndexSearcher searcher = req.getSearcher(); + int[] docIDs = toDocIDs(docs); + + // fetch the unique keys + String[] keys = getUniqueKeys(searcher, docIDs); + + // query-time parameters + String[] fieldNames = getHighlightFields(query, req, defaultFields); + + int maxPassages[] = new int[fieldNames.length]; + for (int i = 0; i < fieldNames.length; i++) { + maxPassages[i] = params.getFieldInt(fieldNames[i], HighlightParams.SNIPPETS, 1); } + + PostingsHighlighter highlighter = getHighlighter(req); + Map snippets = highlighter.highlightFields(fieldNames, query, searcher, docIDs, maxPassages); + return encodeSnippets(keys, fieldNames, snippets); } - + + /** Creates an instance of the Lucene PostingsHighlighter. Provided for subclass extension so that + * a subclass can return a subclass of {@link PostingsSolrHighlighter.SolrExtendedPostingsHighlighter}. */ + protected PostingsHighlighter getHighlighter(SolrQueryRequest req) { + return new SolrExtendedPostingsHighlighter(req); + } + /** * Encodes the resulting snippets into a namedlist * @param keys the document unique keys @@ -261,7 +207,75 @@ public class PostingsSolrHighlighter extends SolrHighlighter implements PluginIn return new String[docIDs.length]; } } - + + /** From {@link #getHighlighter(org.apache.solr.request.SolrQueryRequest)}. */ + public class SolrExtendedPostingsHighlighter extends PostingsHighlighter { + protected final SolrParams params; + protected final IndexSchema schema; + + public SolrExtendedPostingsHighlighter(SolrQueryRequest req) { + super(req.getParams().getInt(HighlightParams.MAX_CHARS, PostingsHighlighter.DEFAULT_MAX_LENGTH)); + this.params = req.getParams(); + this.schema = req.getSchema(); + } + + @Override + protected Passage[] getEmptyHighlight(String fieldName, BreakIterator bi, int maxPassages) { + boolean defaultSummary = params.getFieldBool(fieldName, HighlightParams.DEFAULT_SUMMARY, true); + if (defaultSummary) { + return super.getEmptyHighlight(fieldName, bi, maxPassages); + } else { + //TODO reuse logic of DefaultSolrHighlighter.alternateField + return new Passage[0]; + } + } + + @Override + protected PassageFormatter getFormatter(String fieldName) { + String preTag = params.getFieldParam(fieldName, HighlightParams.TAG_PRE, ""); + String postTag = params.getFieldParam(fieldName, HighlightParams.TAG_POST, ""); + String ellipsis = params.getFieldParam(fieldName, HighlightParams.TAG_ELLIPSIS, "... "); + String encoder = params.getFieldParam(fieldName, HighlightParams.ENCODER, "simple"); + return new DefaultPassageFormatter(preTag, postTag, ellipsis, "html".equals(encoder)); + } + + @Override + protected PassageScorer getScorer(String fieldName) { + float k1 = params.getFieldFloat(fieldName, HighlightParams.SCORE_K1, 1.2f); + float b = params.getFieldFloat(fieldName, HighlightParams.SCORE_B, 0.75f); + float pivot = params.getFieldFloat(fieldName, HighlightParams.SCORE_PIVOT, 87f); + return new PassageScorer(k1, b, pivot); + } + + @Override + protected BreakIterator getBreakIterator(String field) { + String language = params.getFieldParam(field, HighlightParams.BS_LANGUAGE); + String country = params.getFieldParam(field, HighlightParams.BS_COUNTRY); + String variant = params.getFieldParam(field, HighlightParams.BS_VARIANT); + Locale locale = parseLocale(language, country, variant); + String type = params.getFieldParam(field, HighlightParams.BS_TYPE); + return parseBreakIterator(type, locale); + } + + @Override + protected char getMultiValuedSeparator(String field) { + String sep = params.getFieldParam(field, HighlightParams.MULTI_VALUED_SEPARATOR, " "); + if (sep.length() != 1) { + throw new IllegalArgumentException(HighlightParams.MULTI_VALUED_SEPARATOR + " must be exactly one character."); + } + return sep.charAt(0); + } + + @Override + protected Analyzer getIndexAnalyzer(String field) { + if (params.getFieldBool(field, HighlightParams.HIGHLIGHT_MULTI_TERM, false)) { + return schema.getIndexAnalyzer(); + } else { + return null; + } + } + } + /** parse a break iterator type for the specified locale */ protected BreakIterator parseBreakIterator(String type, Locale locale) { if (type == null || "SENTENCE".equals(type)) {