問題:
使用中科院的中文分詞對“中華人民共和國” 進行索引,它被分詞為"中華", "人民", "共和國",用“人民共和國”進行搜尋,可以搜到,而搜尋"中華共和國"卻搜尋不到,用“中華 AND 共和國”卻可以搜出來,為什嗎?
回答:
我下載了http://ictclas.org/Download.html中科院的詞做了簡單的分析,如果索引的時候“中華人民共和國”被分成了“中華”“人民”“共和國”,而搜尋的時候,搜“中華共和國”,則被分為了“中華 共和國”,然而構建Query Parser構建Query Object的時候,卻將它構建成了PhraseQuery—— contents:"中華 共和國" ,而非BooleanQuery——contents:中華 contents:共和國,根據PhraseQuery的解釋,它有一個參數slop來表示兩個詞之間的距離,預設為0,也即只有在文檔不但包含“中華”而且包含“共和國”並且二者相鄰的時候才能返回。這就是為什麼“人民共和國”可以搜出來(它構建的是PhraseQuery,但是相鄰),“中華 AND 共和國”能搜尋出來(它構建的是BooleanQuery),而“中華共和國”搜不出來的原因(它構建的是PhraseQuery,但不相鄰)。
嘗試解析Query query = parser.parse("\"中華共和國\"~1")
或者用API設定Slop為1,就能搜尋出結果了。
Query query = parser.parse("中華共和國"); PhraseQuery pquery = (PhraseQuery)query; pquery.setSlop(1); |
執行個體:
Analyzer ca = new ChineseAnalyzer();
QueryParser parser = new QueryParser(field, ca);
Query query1 = parser.parse("人民共和國");
System.out.println("Searching for: " + query1.toString(field));
查詢對象為:
query1 PhraseQuery (id=39) boost 1.0 field "contents" maxPosition 1 positions ArrayList<E> (id=45) slop 0 terms ArrayList<E> (id=49) elementData Object[4] (id=74) [0] Term (id=76) field "contents" text "人民" [1] Term (id=77) field "contents" text "共和國" |
相當於查詢語句:
Query query2 = parser.parse("中華 AND 共和國");
System.out.println("Searching for: " + query2.toString(field));
查詢對象為:
query2 BooleanQuery (id=43) boost 1.0 clauses ArrayList<E> (id=56) elementData Object[10] (id=57) [0] BooleanClause (id=59) occur BooleanClause$Occur (id=62) name "MUST" query TermQuery (id=65) boost 1.0 term Term (id=70) field "contents" text "中華" [1] BooleanClause (id=61) occur BooleanClause$Occur (id=62) name "MUST" query TermQuery (id=64) boost 1.0 term Term (id=68) field "contents" text "共和國" |
相當於查詢語句:
Query query3 = parser.parse("\"中華共和國\"~1");
System.out.println("Searching for: " + query3.toString(field));
查詢對象為:
query3 PhraseQuery (id=54) boost 1.0 field "contents" maxPosition 1 positions ArrayList<E> (id=93) slop 1 terms ArrayList<E> (id=94) elementData Object[4] (id=96) [0] Term (id=97) field "contents" text "中華" [1] Term (id=98) field "contents" text "共和國" |
相當於查詢語句:
| Searching for: "中華 共和國"~1 |
Query query4 = parser.parse("中華共和國");
PhraseQuery pquery = (PhraseQuery)query4;
pquery.setSlop(1);
System.out.println("Searching for: " + query4.toString(field));
查詢對象為:
query4 PhraseQuery (id=55) boost 1.0 field "contents" maxPosition 1 positions ArrayList<E> (id=102) slop 1 terms ArrayList<E> (id=103) elementData Object[4] (id=105) [0] Term (id=107) field "contents" text "中華" [1] Term (id=108) field "contents" text "共和國" |
相當於查詢語句:
| Searching for: "中華 共和國"~1 |