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

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



    /**
     * 
     * @描述:用于完成拼音加汉字  组合情况的搜索建议   ---尽量少用 
     * @param params
     * @return
     * @return ResultData<List<BaseSuggestIndex>>
     * @exception
     * @createTime:2016年3月30日
     * @author: songqinghu
     */
    @RequestMapping(value="/more.json")
    @ResponseBody    
    public ResultData<List<BaseSuggestIndex>> moreAuto(SearchParams params){
        
        ResultData<List<BaseSuggestIndex>> result = querySuggestServiceImpl.detailedSearch(params);
        
        if(result ==null){
            result =  new ResultData<List<BaseSuggestIndex>>();
            result.setSuccess(false);
        }
        return result;
    }

   /**
     * 进行匹配模式的查询---如果是拼音+汉字形式  转汉字为拼音
     */
    @Override
    public ResultData<List<BaseSuggestIndex>> detailedSearch(SearchParams params) {
        
        String q = params.getQ();
        
        SolrQuery query = new  SolrQuery();
        
        Formula f = new Formula();
        
        if(q != null && q.trim().length()>0){
            
            String[] matching = SearchMachinUtils.getMatching(q);
            for (int i = 0; i < matching.length; i++) {
                
                 f.append(new Query(BaseSuggestIndex.Fd.suggest.name(), matching[i]));
                 f.append(f.tagB());
                 if(i != matching.length-1){
                     f.append(f.tagO());
                     f.append(f.tagB());
                 }
            }
        }

      //设置显示的 字段 --固定值 word
      if(params.getFl() !=null && params.getFl().length()>0){
          query.set(CommonParams.FL,params.getFl());
      }
      //过滤的类型--确定属性
      if(params.getType() !=null && params.getType().trim().length()>0){
          query.setFilterQueries(BaseSuggestIndex.Fd.type.name()+":"+params.getType());
      }
      String exe  = f.toString();
      //主条件--如果传过来的是空   ---先暂时返回空  以后可能返回热词语
      if(exe.isEmpty()){
          ResultData<List<BaseSuggestIndex>> result = new ResultData<List<BaseSuggestIndex>>();
          result.setData(null);
          result.setTotalCount(0l);
          result.setSuccess(false);
          result.setMessage("查询条件为空");
          return result;
      }
      query.set(CommonParams.Q,exe);
      query.setStart(params.getStart());
      query.setRows(params.getRows());
      query.setSort(BaseSuggestIndex.Fd.count.name(), ORDER.desc);
      
      //查询结果
      try {
          QueryResponse response = solrClient.query(query);
          long numFound = response.getResults().getNumFound();
          List<BaseSuggestIndex> words = response.getBeans(BaseSuggestIndex.class);
          logger.info("Date={},formula={},NumFound={}",new Date(), exe,numFound);
          
          ResultData<List<BaseSuggestIndex>> result = new ResultData<List<BaseSuggestIndex>>();
          result.setData(words);
          result.setTotalCount(numFound);
          result.setSuccess(true);
          return result;
      } catch (Exception e) {
          logger.error(" q={} in job solr query fail.", query.getQuery(), e);
          return null;
      }
    }

转换工具类

package cn.com.mx.gome.search.core.util;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 对查询主条件进行处理
 * 形式  数字  拼音  汉字  进行模糊匹配查询 
 * @author songqinghu
 *
 */
public class SearchMachinUtils {

    private  static Logger logger = LoggerFactory.getLogger(Pinyin4jUtil.class);
    
    /**
     * 
     * @描述:对查询条件进行处理 获取匹配条件
     * @param condition
     * @return
     * @return String[]
     * @exception
     * @createTime:2016年3月30日
     * @author: songqinghu
     */
    private static StringBuffer getpinyin(String condition){
        
        //设置字符容器类
        StringBuffer pinyinName = new StringBuffer();
        char[] chars = condition.toCharArray();
        //设置拼音转换器
        HanyuPinyinOutputFormat defaultFormat = new  HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        //判断转换拼凑----关键在这里
        for (char c : chars) {
            if(c>128){
                try {
                    String[] strs = PinyinHelper.toHanyuPinyinStringArray(c, defaultFormat);
                    if(strs !=null){
                        for (int i = 0; i < strs.length; i++) {
                            pinyinName.append(strs[i]+"*");// 测试  ceshi*---
                            if( i != strs.length -1){
                                pinyinName.append(",");
                            }
                        }
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    logger.error("",e);
                }
            }else if( c >=48 && c<=57  ){//0-9---查询匹配
                pinyinName.append(c+"*"); 
            }else if( c >=65 && c<=90){//A-Z
                pinyinName.append(c+"*");
            }else if( c >=97 && c<=122){//a-z
                pinyinName.append(c+"*");
            }
            pinyinName.append(" "); 
        }
        return pinyinName;
    }
    
    /**
     * 去除多音字重复数据
     * 
     * @param theStr
     * @return
     */ 
    private static List<Map<String, Integer>> discountTheChinese(String theStr) { 
        // 去除重复拼音后的拼音列表 
        List<Map<String, Integer>> mapList = new ArrayList<Map<String, Integer>>(); 
        // 用于处理每个字的多音字,去掉重复 
        Map<String, Integer> onlyOne = null; 
        String[] firsts = theStr.split(" "); 
        // 读出每个汉字的拼音 
        for (String str : firsts) { 
            onlyOne = new Hashtable<String, Integer>(); 
            String[] china = str.split(","); 
            // 多音字处理 
            for (String s : china) { 
                Integer count = onlyOne.get(s); 
                if (count == null) { 
                    onlyOne.put(s, new Integer(1)); 
                } else { 
                    onlyOne.remove(s); 
                    count++; 
                    onlyOne.put(s, count); 
                } 
            } 
            mapList.add(onlyOne); 
        } 
        return mapList; 
    } 
    
    /**
     * 解析并组合拼音,对象合并方案(推荐使用)---返回set<String>
     * 
     * @return
     */ 
    private static  String[]  parseTheChinese( 
            List<Map<String, Integer>> list) { 
        Map<String, Integer> first = MinparseTheChineseByObject(list);
        String [] result = null;
        if (first != null && first.keySet().size()>0) { 
            // 遍历取出组合字符串 
            Set<String> set = first.keySet();
            result = new String[set.size()];
            int i = 0;
            for (String string : set) {
                result[i] = string;
                i++;
            }
        } 
        return result; 
    } 
    
    
    /**
     * 
     * @描述:方法抽取
     * @param list
     * @return
     * @return Map<String,Integer>
     * @exception
     * @createTime:2016年3月22日
     * @author: songqinghu
     */
     private static Map<String,Integer> MinparseTheChineseByObject(
             List<Map<String, Integer>> list){
         Map<String, Integer> first = null; // 用于统计每一次,集合组合数据 
         // 遍历每一组集合 
         for (int i = 0; i < list.size(); i++) { 
             // 每一组集合与上一次组合的Map 
             Map<String, Integer> temp = new Hashtable<String, Integer>(); 
             // 第一次循环,first为空 
             if (first != null) { 
                 // 取出上次组合与此次集合的字符,并保存 
                 for (String s : first.keySet()) { 
                     for (String s1 : list.get(i).keySet()) { 
                         String str = s + s1; 
                         temp.put(str, 1); 
                     } 
                 } 
                 // 清理上一次组合数据 
                 if (temp != null && temp.size() > 0) { 
                     first.clear(); 
                 } 
             } else { 
                 for (String s : list.get(i).keySet()) { 
                     String str = s; 
                     temp.put(str, 1); 
                 } 
             } 
             // 保存组合数据以便下次循环使用 
             if (temp != null && temp.size() > 0) { 
                 first = temp; 
             } 
         } 
         return first;
     }
     
    
    public static String[] getMatching(String condition){
        
        return parseTheChinese(discountTheChinese(getpinyin(condition).toString())); 
    }
    
    
}



上一张查询的图片:








评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值