1. 程式人生 > >Solr 數字字元不能搜尋的一個問題

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;
	}