瀏覽代碼

fix #1343 use prefix query

Shinsuke Sugaya 7 年之前
父節點
當前提交
2d149166d6

+ 22 - 4
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) {

+ 35 - 0
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) {