Solr 數字字元不能搜尋的一個問題
問題一: 測試人員告訴我數字不能被搜尋。於是開始找原因:
<fields>
***<field name="productName" type="text"indexed="true" stored="true" />
***
</fields>
fieldType text配置:
<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50" side="front"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50" side="front"/>
</analyzer>
</fieldType>
當我的productName中包含數字字元的時。比如有個產品的名字叫 ‘嘎嘎噶123’ 那麼用數字1/2/3/12等等都不能搜尋到
當時‘123嘎嘎噶’時也是一樣。找了好久沒有找到原因。也不知道怎麼去找這個原因。於是邊問噴油。猜想是分詞的問題。於是邊看Solr的管理介面看能發現點啥?
終於QQ群裡一哥們說 solr.LowerCaseTokenizerFactory
會過濾掉數字 在Solr的Analysis 選單下 看到了可以進行分詞的演示正對當前的schema.xml配置。還可以選擇相應的 field 一試 果真是LowerCaseTokenizerFactory
這個傢伙的問題。於是尋找替代方案。經過嘗試與搜尋。下面的配置
最終解決了數字不能被搜尋的問題。(相應的屬性也改為此型別)
<fieldType
name="text_inclunum" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50" side="front"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50" side="front"/>
</analyzer>
</fieldType>
由於我們庫裡的產品有拼音欄位。而且是大寫。 如果我用AMXL 搜尋 能搜到相應的拼音。進而搜尋相應的產品阿莫西林。(solr配置了all查詢。拼音欄位copy到了all中。)
可如果我用amxl搜尋則不能搜到。於是我在程式中solr的查詢語句時把查詢值toUpperCase(); 終於解決了小寫字母不能搜尋的問題。
問題二:
但第二天發現引入的了新的問題。如果一個產品是 ‘d阿莫西林’ 那麼我用d阿莫西林
進行搜尋,將不能把 'd阿莫西林'這個產品搜出來。開始不知道為啥,放到Solr的Analysis中一測。發現了。我程式把它變為
‘D阿莫西林’ 進行查詢了。但SOlr中搜索的卻是'd阿莫西林
' ,這次所有已小寫字母打頭的產品。如果用產品全名如‘‘d阿莫西林’進行搜尋(自動補全出來的),將不能搜尋出來。
解決了數字的問題。又遇到了小寫字母的問題。 這次沒有找到個Solr這邊的方案。於是打算修改程式。 思路就是 把程式中SOlr的查詢值變大寫的地方改為。如果查詢的值中有中文則不變大寫。如果沒有則變大寫。
這樣的話。如果產品是有數字的,或者有小寫字母的 都能被搜尋出來。 全字母的也能根據拼音搜尋出來。("solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50")這個就是從左到右一個一個分詞的。
於是 網上搜索一個正則查詢字串中是否有中文:
/**
* 判斷一個字串中是否含有中文
* @param str
* @return
*/
public static boolean isContainsChinese(String str)
{
Matcher matcher = Pattern.compile("[\u4e00-\u9fa5]").matcher(str);
boolean flg = false;
if (matcher.find()) {
flg = true;
}
return flg;
}
public static String toUpperOrNot(String temp)
{
if (temp == null)
return "";
if(StringUtils.isContainsChinese(temp))
{
return temp;
}else
{
return temp.toUpperCase();
}
}
於是在SOLR查詢值的地方呼叫下toUpperOrNot()即可。最好呼叫下下面的轉義。
溫馨提示: Solr查詢中如果查詢值中有特殊字元需要轉義:
public static final String NEAD_TO_CONVERT_CHAR = "([/:()!])";
// solr query need to convert meaning
public static String convertMeaningChar(String temp)
{
if (temp == null)
return "";
temp = temp.replaceAll(NEAD_TO_CONVERT_CHAR, "\\\\$1");
return temp;
}