您的位置:首页 > 其它

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

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

/**
*
* @描述:用于完成拼音加汉字  组合情况的搜索建议   ---尽量少用
* @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()));
}

}


上一张查询的图片:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: