1. 程式人生 > >Elasticsearch之高亮進階-高效能高亮器, 讓Elasticsearch飛一會兒

Elasticsearch之高亮進階-高效能高亮器, 讓Elasticsearch飛一會兒

package org.elasticsearch.search.highlight;

import com.google.common.collect.Maps;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.search.vectorhighlight.BoundaryScanner;
import org.apache.lucene.search.vectorhighlight.CustomFieldQuery;
import org.apache.lucene.search.vectorhighlight.FieldQuery;
import org.apache.lucene.search.vectorhighlight.SimpleBoundaryScanner;
import org.apache.lucene.search.vectorhighlight.FieldQuery.Phrase;
import org.apache.lucene.util.BytesRefHash;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.search.fetch.FetchPhaseExecutionException;
import org.elasticsearch.search.fetch.FetchSubPhase;
import org.elasticsearch.search.internal.SearchContext;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 
 * @author jkuang.nj
 *
 */
public class FastPlainHighlighter implements Highlighter
{
	private static final String CACHE_KEY = "highlight-fast";
	public static final char mark = 0;
	private static final SimpleBoundaryScanner DEFAULT_BOUNDARY_SCANNER = new SimpleBoundaryScanner();

	@Override
	public HighlightField highlight(HighlighterContext highlighterContext)
	{
		SearchContextHighlight.Field field = highlighterContext.field;
		SearchContext context = highlighterContext.context;
		FetchSubPhase.HitContext hitContext = highlighterContext.hitContext;
		FieldMapper mapper = highlighterContext.mapper;
		Encoder encoder = field.fieldOptions().encoder().equals("html") ? HighlightUtils.Encoders.HTML : HighlightUtils.Encoders.DEFAULT;

		if (!hitContext.cache().containsKey(CACHE_KEY))
		{
			hitContext.cache().put(CACHE_KEY, new HighlighterEntry());
		}

		HighlighterEntry cache = (HighlighterEntry) hitContext.cache().get(CACHE_KEY);
		try
		{
			FieldQuery fieldQuery;
			if (field.fieldOptions().requireFieldMatch())
			{
				if (cache.fieldMatchFieldQuery == null)
				{
					cache.fieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query, hitContext.topLevelReader(), true,
							field.fieldOptions().requireFieldMatch());
				}
				fieldQuery = cache.fieldMatchFieldQuery;
			}
			else
			{
				if (cache.noFieldMatchFieldQuery == null)
				{
					cache.noFieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query, hitContext.topLevelReader(), true,
							field.fieldOptions().requireFieldMatch());
				}
				fieldQuery = cache.noFieldMatchFieldQuery;

			}
			if (!cache.analysises.containsKey(field.field()))
			{
				cache.setPhrases(field.field(), fieldQuery.getPhrases(field.field()));
				cache.setWords(field.field(), fieldQuery.getTermSet(field.field()));
			}
			FastHighlighter entry = cache.mappers.get(mapper);
			if (entry == null)
			{

				BoundaryScanner boundaryScanner = DEFAULT_BOUNDARY_SCANNER;
				if (field.fieldOptions().boundaryMaxScan() != SimpleBoundaryScanner.DEFAULT_MAX_SCAN
						|| field.fieldOptions().boundaryChars() != SimpleBoundaryScanner.DEFAULT_BOUNDARY_CHARS)
				{
					boundaryScanner = new SimpleBoundaryScanner(field.fieldOptions().boundaryMaxScan(), field.fieldOptions().boundaryChars());
				}
				CustomFieldQuery.highlightFilters.set(field.fieldOptions().highlightFilter());
				entry = new FastHighlighter(encoder, boundaryScanner);
				cache.mappers.put(mapper, entry);
			}

			String[] fragments;
			int numberOfFragments = field.fieldOptions().numberOfFragments() == 0 ? 1 : field.fieldOptions().numberOfFragments();
			int fragmentCharSize = field.fieldOptions().numberOfFragments() == 0 ? 50 : field.fieldOptions().fragmentCharSize();
			List