All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.search.elasticsearch.internal.ElasticsearchQuerySuggester Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.search.elasticsearch.internal;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.search.DocumentImpl;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.suggest.AggregateSuggester;
import com.liferay.portal.kernel.search.suggest.BaseQuerySuggester;
import com.liferay.portal.kernel.search.suggest.PhraseSuggester;
import com.liferay.portal.kernel.search.suggest.QuerySuggester;
import com.liferay.portal.kernel.search.suggest.Suggester;
import com.liferay.portal.kernel.search.suggest.SuggesterResult;
import com.liferay.portal.kernel.search.suggest.SuggesterResults;
import com.liferay.portal.kernel.search.suggest.SuggesterTranslator;
import com.liferay.portal.kernel.search.suggest.TermSuggester;
import com.liferay.portal.search.elasticsearch.connection.ElasticsearchConnectionManager;
import com.liferay.portal.search.elasticsearch.index.IndexNameBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.time.StopWatch;

import org.elasticsearch.action.suggest.SuggestRequestBuilder;
import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.term.TermSuggestion;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Michael C. Han
 */
@Component(
	immediate = true, property = {"search.engine.impl=Elasticsearch"},
	service = QuerySuggester.class
)
public class ElasticsearchQuerySuggester extends BaseQuerySuggester {

	@Override
	public Map> spellCheckKeywords(
		SearchContext searchContext, int max) {

		String field = DocumentImpl.getLocalizedName(
			searchContext.getLocale(), Field.SPELL_CHECK_WORD);

		TermSuggester termSuggester = new TermSuggester(
			"spellCheckRequest", field, searchContext.getKeywords());

		termSuggester.setSize(max);

		SuggesterResults suggesterResults = suggest(
			searchContext, termSuggester);

		Map> suggestionsMap = new HashMap<>();

		for (SuggesterResult suggesterResult :
				suggesterResults.getSuggesterResults()) {

			for (SuggesterResult.Entry suggesterResultEntry :
					suggesterResult.getEntries()) {

				String text = suggesterResultEntry.getText();

				List suggestionsList = suggestionsMap.get(text);

				if (suggestionsList == null) {
					suggestionsList = new ArrayList<>();

					suggestionsMap.put(text, suggestionsList);
				}

				for (SuggesterResult.Entry.Option suggesterResultEntryOption :
						suggesterResultEntry.getOptions()) {

					suggestionsList.add(suggesterResultEntryOption.getText());
				}
			}
		}

		return suggestionsMap;
	}

	@Override
	public SuggesterResults suggest(
		SearchContext searchContext, Suggester suggester) {

		StopWatch stopWatch = new StopWatch();

		stopWatch.start();

		Client client = elasticsearchConnectionManager.getClient();

		SuggestBuilder suggestBuilder = suggesterTranslator.translate(
			suggester, searchContext);

		SuggestRequestBuilder suggestRequestBuilder = client.prepareSuggest(
			indexNameBuilder.getIndexName(searchContext.getCompanyId()));

		for (SuggestBuilder.SuggestionBuilder suggestionBuilder :
				suggestBuilder.getSuggestion()) {

			suggestRequestBuilder.addSuggestion(suggestionBuilder);
		}

		if (suggester instanceof AggregateSuggester) {
			AggregateSuggester aggregateSuggester =
				(AggregateSuggester)suggester;

			suggestRequestBuilder.setSuggestText(aggregateSuggester.getValue());
		}

		SuggestResponse suggestResponse = suggestRequestBuilder.get();

		Suggest suggest = suggestResponse.getSuggest();

		SuggesterResults suggesterResults = new SuggesterResults();

		for (Suggest.Suggestion
				> suggestion :
						suggest) {

			SuggesterResult suggesterResult = translate(suggestion);

			suggesterResults.addSuggesterResult(suggesterResult);
		}

		if (_log.isInfoEnabled()) {
			stopWatch.stop();

			_log.info(
				"Spell checked keywords in " + stopWatch.getTime() + "ms");
		}

		return suggesterResults;
	}

	@Override
	public String[] suggestKeywordQueries(
		SearchContext searchContext, int max) {

		List keywordQueries = new ArrayList<>();

		String field = DocumentImpl.getLocalizedName(
			searchContext.getLocale(), Field.KEYWORD_SEARCH);

		PhraseSuggester phraseSuggester = new PhraseSuggester(
			"keywordQueryRequest", field, searchContext.getKeywords());

		phraseSuggester.setSize(max);

		SuggesterResults suggesterResults = suggest(
			searchContext, phraseSuggester);

		SuggesterResult suggesterResult = suggesterResults.getSuggesterResult(
			phraseSuggester.getName());

		List suggesterResultEntries =
			suggesterResult.getEntries();

		for (SuggesterResult.Entry suggesterResultEntry :
				suggesterResultEntries) {

			for (SuggesterResult.Entry.Option suggesterResultEntryOption :
					suggesterResultEntry.getOptions()) {

				String optionText = String.valueOf(
					suggesterResultEntryOption.getText());

				keywordQueries.add(optionText);
			}
		}

		return keywordQueries.toArray(new String[keywordQueries.size()]);
	}

	protected SuggesterResult translate(
		Suggest.Suggestion
			> suggestion) {

		SuggesterResult suggesterResult = new SuggesterResult(
			suggestion.getName());

		for (Suggest.Suggestion.Entry
				suggestionEntry : suggestion) {

			SuggesterResult.Entry suggesterResultEntry = translate(
				suggestionEntry);

			suggesterResult.addEntry(suggesterResultEntry);
		}

		return suggesterResult;
	}

	protected SuggesterResult.Entry.Option translate(
		Suggest.Suggestion.Entry.Option suggestionEntryOption) {

		SuggesterResult.Entry.Option suggesterResultEntryOption =
			new SuggesterResult.Entry.Option(
				suggestionEntryOption.getText().string(),
				suggestionEntryOption.getScore());

		if (suggestionEntryOption.getHighlighted() != null) {
			suggesterResultEntryOption.setHighlightedText(
				suggestionEntryOption.getHighlighted().string());
		}

		if (suggestionEntryOption instanceof TermSuggestion.Entry.Option) {
			TermSuggestion.Entry.Option termSuggestionEntryOption =
				(TermSuggestion.Entry.Option)suggestionEntryOption;

			suggesterResultEntryOption.setFrequency(
				termSuggestionEntryOption.getFreq());
		}

		return suggesterResultEntryOption;
	}

	protected SuggesterResult.Entry translate(
		Suggest.Suggestion.Entry
			suggestionEntry) {

		Text text = suggestionEntry.getText();

		SuggesterResult.Entry suggesterResultEntry = new SuggesterResult.Entry(
			text.string());

		List suggestionEntryOptions =
			suggestionEntry.getOptions();

		for (Suggest.Suggestion.Entry.Option suggestionEntryOption :
				suggestionEntryOptions) {

			SuggesterResult.Entry.Option suggesterResultEntryOption = translate(
				suggestionEntryOption);

			suggesterResultEntry.addOption(suggesterResultEntryOption);
		}

		return suggesterResultEntry;
	}

	@Reference(unbind = "-")
	protected ElasticsearchConnectionManager elasticsearchConnectionManager;

	@Reference(unbind = "-")
	protected IndexNameBuilder indexNameBuilder;

	@Reference(target = "(search.engine.impl=Elasticsearch)")
	protected SuggesterTranslator suggesterTranslator;

	private static final Log _log = LogFactoryUtil.getLog(
		ElasticsearchQuerySuggester.class);

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy