/** * 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.internal.analysis; import com.liferay.portal.kernel.search.BooleanClauseOccur; import com.liferay.portal.kernel.search.Query; import com.liferay.portal.kernel.search.generic.BooleanQueryImpl; import com.liferay.portal.kernel.search.generic.MatchQuery; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.search.analysis.KeywordTokenizer; import java.util.ArrayList; import java.util.List; /** * @author André de Oliveira */ public class FullTextQueryBuilder { public FullTextQueryBuilder(KeywordTokenizer keywordTokenizer) { _keywordTokenizer = keywordTokenizer; } public Query build(String field, String keywords) { BooleanQueryImpl booleanQueryImpl = new BooleanQueryImpl(); List<String> tokens = _keywordTokenizer.tokenize(keywords); List<String> phrases = new ArrayList<>(tokens.size()); List<String> words = new ArrayList<>(tokens.size()); for (String token : tokens) { if (StringUtil.startsWith(token, CharPool.QUOTE)) { phrases.add(StringUtil.unquote(token)); } else { words.add(token); } } for (String phrase : phrases) { booleanQueryImpl.add( createPhraseQuery(field, phrase), BooleanClauseOccur.MUST); } if (!words.isEmpty()) { addSentenceQueries( field, StringUtil.merge(words, StringPool.SPACE), booleanQueryImpl); } booleanQueryImpl.add( createExactMatchQuery(field, keywords), BooleanClauseOccur.SHOULD); return booleanQueryImpl; } public void setAutocomplete(boolean autocomplete) { _autocomplete = autocomplete; } public void setExactMatchBoost(float exactMatchBoost) { _exactMatchBoost = exactMatchBoost; } public void setProximitySlop(int proximitySlop) { _proximitySlop = proximitySlop; } protected void addSentenceQueries( String field, String sentence, BooleanQueryImpl booleanQueryImpl) { booleanQueryImpl.add( createMandatoryQuery(field, sentence), BooleanClauseOccur.MUST); if (_proximitySlop != null) { booleanQueryImpl.add( createProximityQuery(field, sentence), BooleanClauseOccur.SHOULD); } } protected Query createAutocompleteQuery(String field, String value) { PhraseQueryBuilder builder = new PhraseQueryBuilder(); builder.setPrefix(true); return builder.build(field, value); } protected Query createExactMatchQuery(String field, String keywords) { PhraseQueryBuilder builder = new PhraseQueryBuilder(); builder.setBoost(_exactMatchBoost); return builder.build(field, keywords); } protected Query createMandatoryQuery(String field, String sentence) { Query matchQuery = createMatchQuery(field, sentence); if (!_autocomplete) { return matchQuery; } BooleanQueryImpl booleanQueryImpl = new BooleanQueryImpl(); booleanQueryImpl.add(matchQuery, BooleanClauseOccur.SHOULD); booleanQueryImpl.add( createAutocompleteQuery(field, sentence), BooleanClauseOccur.SHOULD); return booleanQueryImpl; } protected Query createMatchQuery(String field, String value) { return new MatchQuery(field, value); } protected Query createPhraseQuery(String field, String phrase) { PhraseQueryBuilder builder = new PhraseQueryBuilder(); builder.setTrailingStarAware(true); return builder.build(field, phrase); } protected Query createProximityQuery(String field, String value) { PhraseQueryBuilder builder = new PhraseQueryBuilder(); builder.setSlop(_proximitySlop); return builder.build(field, value); } private boolean _autocomplete; private float _exactMatchBoost; private final KeywordTokenizer _keywordTokenizer; private Integer _proximitySlop; }