solr入门之拼音加汉字方式的搜索建议自动补全的不高效实现

转载自:http://blog.csdn.net/sqh201030412/article/details/51018294

今天思考实现了下字符加汉字的搜索建议的 实现--思想主要还是昨天的思想,不过这个方法使用的是匹配查询 ,查询速度可能不太理想



[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  *  
  3.  * @描述:用于完成拼音加汉字  组合情况的搜索建议   ---尽量少用  
  4.  * @param params 
  5.  * @return 
  6.  * @return ResultData<List<BaseSuggestIndex>> 
  7.  * @exception 
  8.  * @createTime:2016年3月30日 
  9.  * @author: songqinghu 
  10.  */  
  11. @RequestMapping(value="/more.json")  
  12. @ResponseBody      
  13. public ResultData<List<BaseSuggestIndex>> moreAuto(SearchParams params){  
  14.       
  15.     ResultData<List<BaseSuggestIndex>> result = querySuggestServiceImpl.detailedSearch(params);  
  16.       
  17.     if(result ==null){  
  18.         result =  new ResultData<List<BaseSuggestIndex>>();  
  19.         result.setSuccess(false);  
  20.     }  
  21.     return result;  
  22. }  

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.   * 进行匹配模式的查询---如果是拼音+汉字形式  转汉字为拼音 
  3.   */  
  4.  @Override  
  5.  public ResultData<List<BaseSuggestIndex>> detailedSearch(SearchParams params) {  
  6.        
  7.      String q = params.getQ();  
  8.        
  9.      SolrQuery query = new  SolrQuery();  
  10.        
  11.      Formula f = new Formula();  
  12.        
  13.      if(q != null && q.trim().length()>0){  
  14.            
  15.          String[] matching = SearchMachinUtils.getMatching(q);  
  16.          for (int i = 0; i < matching.length; i++) {  
  17.                
  18.               f.append(new Query(BaseSuggestIndex.Fd.suggest.name(), matching[i]));  
  19.               f.append(f.tagB());  
  20.               if(i != matching.length-1){  
  21.                   f.append(f.tagO());  
  22.                   f.append(f.tagB());  
  23.               }  
  24.          }  
  25.      }  
  26.   
  27.    //设置显示的 字段 --固定值 word  
  28.    if(params.getFl() !=null && params.getFl().length()>0){  
  29.        query.set(CommonParams.FL,params.getFl());  
  30.    }  
  31.    //过滤的类型--确定属性  
  32.    if(params.getType() !=null && params.getType().trim().length()>0){  
  33.        query.setFilterQueries(BaseSuggestIndex.Fd.type.name()+":"+params.getType());  
  34.    }  
  35.    String exe  = f.toString();  
  36.    //主条件--如果传过来的是空   ---先暂时返回空  以后可能返回热词语  
  37.    if(exe.isEmpty()){  
  38.        ResultData<List<BaseSuggestIndex>> result = new ResultData<List<BaseSuggestIndex>>();  
  39.        result.setData(null);  
  40.        result.setTotalCount(0l);  
  41.        result.setSuccess(false);  
  42.        result.setMessage("查询条件为空");  
  43.        return result;  
  44.    }  
  45.    query.set(CommonParams.Q,exe);  
  46.    query.setStart(params.getStart());  
  47.    query.setRows(params.getRows());  
  48.    query.setSort(BaseSuggestIndex.Fd.count.name(), ORDER.desc);  
  49.      
  50.    //查询结果  
  51.    try {  
  52.        QueryResponse response = solrClient.query(query);  
  53.        long numFound = response.getResults().getNumFound();  
  54.        List<BaseSuggestIndex> words = response.getBeans(BaseSuggestIndex.class);  
  55.        logger.info("Date={},formula={},NumFound={}",new Date(), exe,numFound);  
  56.          
  57.        ResultData<List<BaseSuggestIndex>> result = new ResultData<List<BaseSuggestIndex>>();  
  58.        result.setData(words);  
  59.        result.setTotalCount(numFound);  
  60.        result.setSuccess(true);  
  61.        return result;  
  62.    } catch (Exception e) {  
  63.        logger.error(" q={} in job solr query fail.", query.getQuery(), e);  
  64.        return null;  
  65.    }  
  66.  }  

转换工具类

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package cn.com.mx.gome.search.core.util;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Hashtable;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import java.util.Set;  
  8.   
  9. import org.slf4j.Logger;  
  10. import org.slf4j.LoggerFactory;  
  11.   
  12. import net.sourceforge.pinyin4j.PinyinHelper;  
  13. import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;  
  14. import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;  
  15. import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;  
  16. import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;  
  17.   
  18. /** 
  19.  * 对查询主条件进行处理 
  20.  * 形式  数字  拼音  汉字  进行模糊匹配查询  
  21.  * @author songqinghu 
  22.  * 
  23.  */  
  24. public class SearchMachinUtils {  
  25.   
  26.     private  static Logger logger = LoggerFactory.getLogger(Pinyin4jUtil.class);  
  27.       
  28.     /** 
  29.      *  
  30.      * @描述:对查询条件进行处理 获取匹配条件 
  31.      * @param condition 
  32.      * @return 
  33.      * @return String[] 
  34.      * @exception 
  35.      * @createTime:2016年3月30日 
  36.      * @author: songqinghu 
  37.      */  
  38.     private static StringBuffer getpinyin(String condition){  
  39.           
  40.         //设置字符容器类  
  41.         StringBuffer pinyinName = new StringBuffer();  
  42.         char[] chars = condition.toCharArray();  
  43.         //设置拼音转换器  
  44.         HanyuPinyinOutputFormat defaultFormat = new  HanyuPinyinOutputFormat();  
  45.         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  46.         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  47.         //判断转换拼凑----关键在这里  
  48.         for (char c : chars) {  
  49.             if(c>128){  
  50.                 try {  
  51.                     String[] strs = PinyinHelper.toHanyuPinyinStringArray(c, defaultFormat);  
  52.                     if(strs !=null){  
  53.                         for (int i = 0; i < strs.length; i++) {  
  54.                             pinyinName.append(strs[i]+"*");// 测试  ceshi*---  
  55.                             if( i != strs.length -1){  
  56.                                 pinyinName.append(",");  
  57.                             }  
  58.                         }  
  59.                     }  
  60.                 } catch (BadHanyuPinyinOutputFormatCombination e) {  
  61.                     logger.error("",e);  
  62.                 }  
  63.             }else if( c >=48 && c<=57  ){//0-9---查询匹配  
  64.                 pinyinName.append(c+"*");   
  65.             }else if( c >=65 && c<=90){//A-Z  
  66.                 pinyinName.append(c+"*");  
  67.             }else if( c >=97 && c<=122){//a-z  
  68.                 pinyinName.append(c+"*");  
  69.             }  
  70.             pinyinName.append(" ");   
  71.         }  
  72.         return pinyinName;  
  73.     }  
  74.       
  75.     /** 
  76.      * 去除多音字重复数据 
  77.      *  
  78.      * @param theStr 
  79.      * @return 
  80.      */   
  81.     private static List<Map<String, Integer>> discountTheChinese(String theStr) {   
  82.         // 去除重复拼音后的拼音列表   
  83.         List<Map<String, Integer>> mapList = new ArrayList<Map<String, Integer>>();   
  84.         // 用于处理每个字的多音字,去掉重复   
  85.         Map<String, Integer> onlyOne = null;   
  86.         String[] firsts = theStr.split(" ");   
  87.         // 读出每个汉字的拼音   
  88.         for (String str : firsts) {   
  89.             onlyOne = new Hashtable<String, Integer>();   
  90.             String[] china = str.split(",");   
  91.             // 多音字处理   
  92.             for (String s : china) {   
  93.                 Integer count = onlyOne.get(s);   
  94.                 if (count == null) {   
  95.                     onlyOne.put(s, new Integer(1));   
  96.                 } else {   
  97.                     onlyOne.remove(s);   
  98.                     count++;   
  99.                     onlyOne.put(s, count);   
  100.                 }   
  101.             }   
  102.             mapList.add(onlyOne);   
  103.         }   
  104.         return mapList;   
  105.     }   
  106.       
  107.     /** 
  108.      * 解析并组合拼音,对象合并方案(推荐使用)---返回set<String> 
  109.      *  
  110.      * @return 
  111.      */   
  112.     private static  String[]  parseTheChinese(   
  113.             List<Map<String, Integer>> list) {   
  114.         Map<String, Integer> first = MinparseTheChineseByObject(list);  
  115.         String [] result = null;  
  116.         if (first != null && first.keySet().size()>0) {   
  117.             // 遍历取出组合字符串   
  118.             Set<String> set = first.keySet();  
  119.             result = new String[set.size()];  
  120.             int i = 0;  
  121.             for (String string : set) {  
  122.                 result[i] = string;  
  123.                 i++;  
  124.             }  
  125.         }   
  126.         return result;   
  127.     }   
  128.       
  129.       
  130.     /** 
  131.      *  
  132.      * @描述:方法抽取 
  133.      * @param list 
  134.      * @return 
  135.      * @return Map<String,Integer> 
  136.      * @exception 
  137.      * @createTime:2016年3月22日 
  138.      * @author: songqinghu 
  139.      */  
  140.      private static Map<String,Integer> MinparseTheChineseByObject(  
  141.              List<Map<String, Integer>> list){  
  142.          Map<String, Integer> first = null// 用于统计每一次,集合组合数据   
  143.          // 遍历每一组集合   
  144.          for (int i = 0; i < list.size(); i++) {   
  145.              // 每一组集合与上一次组合的Map   
  146.              Map<String, Integer> temp = new Hashtable<String, Integer>();   
  147.              // 第一次循环,first为空   
  148.              if (first != null) {   
  149.                  // 取出上次组合与此次集合的字符,并保存   
  150.                  for (String s : first.keySet()) {   
  151.                      for (String s1 : list.get(i).keySet()) {   
  152.                          String str = s + s1;   
  153.                          temp.put(str, 1);   
  154.                      }   
  155.                  }   
  156.                  // 清理上一次组合数据   
  157.                  if (temp != null && temp.size() > 0) {   
  158.                      first.clear();   
  159.                  }   
  160.              } else {   
  161.                  for (String s : list.get(i).keySet()) {   
  162.                      String str = s;   
  163.                      temp.put(str, 1);   
  164.                  }   
  165.              }   
  166.              // 保存组合数据以便下次循环使用   
  167.              if (temp != null && temp.size() > 0) {   
  168.                  first = temp;   
  169.              }   
  170.          }   
  171.          return first;  
  172.      }  
  173.        
  174.       
  175.     public static String[] getMatching(String condition){  
  176.           
  177.         return parseTheChinese(discountTheChinese(getpinyin(condition).toString()));   
  178.     }  
  179.       
  180.       
  181. }  



上一张查询的图片:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值