diff --git a/src/main/java/org/codelibs/fess/helper/QueryHelper.java b/src/main/java/org/codelibs/fess/helper/QueryHelper.java index 04e592dca..74cd0e5c6 100644 --- a/src/main/java/org/codelibs/fess/helper/QueryHelper.java +++ b/src/main/java/org/codelibs/fess/helper/QueryHelper.java @@ -17,6 +17,7 @@ package org.codelibs.fess.helper; import static org.codelibs.core.stream.StreamUtil.stream; +import java.lang.Character.UnicodeBlock; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -505,6 +506,23 @@ public class QueryHelper { } } + protected QueryBuilder buildMatchPhraseQuery(final String f, final String text) { + if (text == null || text.length() != 1 + || (!fessConfig.getIndexFieldTitle().equals(f) && !fessConfig.getIndexFieldContent().equals(f))) { + return QueryBuilders.matchPhraseQuery(f, text); + } + + UnicodeBlock block = UnicodeBlock.of(text.codePointAt(0)); + if (block == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS // + || block == UnicodeBlock.HIRAGANA // + || block == UnicodeBlock.KATAKANA // + || block == UnicodeBlock.HANGUL_SYLLABLES // + ) { + return QueryBuilders.prefixQuery(f, text); + } + return QueryBuilders.matchPhraseQuery(f, text); + } + protected QueryBuilder convertTermQuery(final QueryContext context, final TermQuery termQuery, final float boost) { final String field = termQuery.getTerm().field(); final String text = termQuery.getTerm().text(); @@ -513,7 +531,7 @@ public class QueryHelper { } else if (Constants.DEFAULT_FIELD.equals(field)) { context.addFieldLog(field, text); context.addHighlightedQuery(text); - return buildDefaultQueryBuilder((f, b) -> QueryBuilders.matchPhraseQuery(f, text).boost(b * boost)); + return buildDefaultQueryBuilder((f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost)); } else if ("sort".equals(field)) { final String[] values = text.split("\\."); if (values.length > 2) { @@ -546,13 +564,13 @@ public class QueryHelper { if (notAnalyzedFieldSet.contains(field)) { return QueryBuilders.termQuery(field, text).boost(boost); } else { - return QueryBuilders.matchPhraseQuery(field, text).boost(boost); + return buildMatchPhraseQuery(field, text).boost(boost); } } else { final String origQuery = termQuery.toString(); context.addFieldLog(Constants.DEFAULT_FIELD, origQuery); context.addHighlightedQuery(origQuery); - return buildDefaultQueryBuilder((f, b) -> QueryBuilders.matchPhraseQuery(f, origQuery).boost(b * boost)); + return buildDefaultQueryBuilder((f, b) -> buildMatchPhraseQuery(f, origQuery).boost(b * boost)); } } @@ -567,7 +585,7 @@ public class QueryHelper { final String text = String.join(" ", texts); context.addFieldLog(field, text); stream(texts).of(stream -> stream.forEach(t -> context.addHighlightedQuery(t))); - return buildDefaultQueryBuilder((f, b) -> QueryBuilders.matchPhraseQuery(f, text).boost(b * boost)); + return buildDefaultQueryBuilder((f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost)); } private boolean isSearchField(final String field) { diff --git a/src/test/java/org/codelibs/fess/helper/QueryHelperTest.java b/src/test/java/org/codelibs/fess/helper/QueryHelperTest.java index 85aec53b2..55217d8a3 100644 --- a/src/test/java/org/codelibs/fess/helper/QueryHelperTest.java +++ b/src/test/java/org/codelibs/fess/helper/QueryHelperTest.java @@ -28,6 +28,8 @@ import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.unit.UnitFessTestCase; import org.codelibs.fess.util.ComponentUtil; import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.MatchPhraseQueryBuilder; +import org.elasticsearch.index.query.PrefixQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; @@ -79,6 +81,39 @@ public class QueryHelperTest extends UnitFessTestCase { assertQuery( functionScoreQuery(orQuery(simpleQuery("QUERY1", titleBoost, contentBoost), simpleQuery("QUERY2", titleBoost, contentBoost))), buildQuery("QUERY1 OR QUERY2")); + + assertQueryBuilder("test", "", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "test", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "a", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "あ", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "ア", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "亜", MatchPhraseQueryBuilder.class); + assertQueryBuilder("test", "아", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "test", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "a", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "あ", PrefixQueryBuilder.class); + assertQueryBuilder("title", "ああ", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "ア", PrefixQueryBuilder.class); + assertQueryBuilder("title", "アア", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "亜", PrefixQueryBuilder.class); + assertQueryBuilder("title", "亜亜", MatchPhraseQueryBuilder.class); + assertQueryBuilder("title", "아", PrefixQueryBuilder.class); + assertQueryBuilder("title", "아아", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "test", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "a", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "あ", PrefixQueryBuilder.class); + assertQueryBuilder("content", "ああ", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "ア", PrefixQueryBuilder.class); + assertQueryBuilder("content", "アア", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "亜", PrefixQueryBuilder.class); + assertQueryBuilder("content", "亜亜", MatchPhraseQueryBuilder.class); + assertQueryBuilder("content", "아", PrefixQueryBuilder.class); + assertQueryBuilder("content", "아아", MatchPhraseQueryBuilder.class); + } + + private void assertQueryBuilder(String field, String value, Class clazz) { + QueryBuilder queryBuilder = queryHelper.buildMatchPhraseQuery(field, value); + assertEquals(clazz, queryBuilder.getClass()); } private QueryBuilder andQuery(QueryBuilder... queries) {