elasticsearch 实现联想输入搜索 |
您所在的位置:网站首页 › java实现关键词搜索 › elasticsearch 实现联想输入搜索 |
通常,在项目中需要联想输入(即输入关键字,提示相关词条,类似百度google的搜索)的需求,可能大家都是用的数据库的like '%关键字%‘来实现。但是这样实现有几个问题。 第一、这样的搜索无论是oracle还是mysql,都是无法使用索引的。在oracle中可能有全文检索可以使用,但是个人感觉效果不是很好。 第二、输入的关键字有like的通病,就是只有保含关键字的词条才会被命中。如果中间加个空格之类的,db就无能为力了。 第三、如果要想对命中结果进行相关度排序,这个在常规数据库是无法做到的。虽然,可以按照命中词条的长度进行升序排序,但是加上排序,性能不是很好。
下面介绍一下使用elasticsearch实现联想输入的搜索,因为是搜索引擎,天生就不具备上面的3个问题。 在具体介绍使用方法之前,我们先找个搜索数据。我找的是ICD(就是疾病名称的国标),谁让咱一生都在跟他做斗争。这个在网上一搜一堆。 有了数据,我们先要简单描述一下我们要达到的一个目的。一般的搜索都支持汉字 和拼音两种检索方法。我们的这个检索也满足这个需求。
搜索需求描述: 1、支持汉字和简拼两种搜索方法。 2、输入“高血压”时,按照相关度,将带“高血压”名称的疾病名称按照相关度降序排序。 3、输入“老年 高血压”,时,将带“老年”和“高血压”名称的疾病名称按照相关度降序排序。 4、输入拼音'gxy‘时,将拼音中带有gxy相关的疾病按照相关度降序排序。 ....
类似测试用例的需求,到此打住。
那么,我们一步一步实现这种需求。 首先,我们定义了一个ICD的类,算作我们的模型,其实没有模型也可以,只要存入到es且知道各个field的名称就行。这个里面我们只需要关注疾病名称diseaseName及简拼pinyin字段即可,这个字段默认是字符串,ES默认会帮我们分词。 Java代码import java.io.Serializable; import java.math.BigDecimal; /** * ICD抽象对象 * @author [email protected] */ public class ICD implements Serializable{ private static final long serialVersionUID = 6934803011248581109L; //疾病ID private int id; //疾病编码 private String code; //疾病名称 private String diseaseName; //疾病加拼音 private String mergeName; //汉语拼音简拼 private String pinyin; //是否恶心肿瘤 private boolean isTherioma; //是否住院特殊病种 private boolean isSpecialDisease;
public ICD(BigDecimal id, String diseaseName, String code, String pinyin, String isTherioma, String isSpecialDisease) { this.id = id.intValue(); this.diseaseName = diseaseName; this.code = code; this.pinyin = pinyin; if("是".equals(isTherioma)){ this.isTherioma = true; } else { this.isTherioma = false; }
if("是".equals(isSpecialDisease)){ this.isSpecialDisease = true; } else { this.isSpecialDisease = false; } this.mergeName = diseaseName + "," + pinyin; } //set,get ......
}
第二步,将数据存储到elasticsearch里面,我们取个名称叫code,起个type名称叫icd。ICD大概2w条数据,我使用默认的bulkIndex,存到es大概用了3秒。 我这里是把数据从oracle导入到elasticsearch。 Java代码import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List;
import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.client.Client;
import com.donlianli.es.ESUtils; import com.donlianli.es.db.DatabaseUtils;
public class ICDManager {
public static void main(String[] argvs){ ICDManager manager = new ICDManager(); manager.indexDataDirect(); } /** * 直接将数据初始化到ES中 * 不创建mapping */ private void indexDataDirect() { List icdList = getIcdListFromDB(); System.out.println(" get icd from db finish,size:" + icdList.size()); bulkIndex(icdList); }
private void bulkIndex(List icdList) { Client client = ESUtils.getCodeClient(); BulkRequestBuilder bulkRequest = client.prepareBulk(); long b = System.currentTimeMillis(); for(int i=0,l=icdList.size();i |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |