转载自:http://blog.youkuaiyun.com/sqh201030412/article/details/51018294
今天思考实现了下字符加汉字的搜索建议的 实现--思想主要还是昨天的思想,不过这个方法使用的是匹配查询 ,查询速度可能不太理想
- /**
- *
- * @描述:用于完成拼音加汉字 组合情况的搜索建议 ---尽量少用
- * @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()));
- }
- }
上一张查询的图片: