记录一次elasticsearch模糊匹配
【记录一次elasticsearch模糊匹配】在接触elasticsearch的时候,起初我是想用这个技术对外封装所有的接口,但是有些想法始终不是现实,刚开始接触的时候搜索的确带来速度的快感,所以用这门技术对任何需求进行了CRUD;闲话少说,现在来介绍下使用过程中遇到小问题,需求如下:
- 实现如mysql 中的 like查询 %XXXXXX%
- 基于elasticsearch实现完全匹配如 like %XXXXXX%
- 例如有个字段数据为“张三” 那么必须用 '张' -‘三’-‘张三’等三个词都能查询到对应的数据
- ik在线分词测试 https://www.itgongju.com/ikAn...
- ansj在线分词测试 https://www.itgongju.com/ansj...
首先我的思路是使用WildCardQuery进行查询(前提是es中的查询字段不能分词),下面我们来看具体代码,下面的代码主要是创建不带分词的索引(直接采用了Junit进行了测试)
/**
* @Description: TODO(创建不带分词的索引2)
*/
@Test
public void createIndex2() throws Exception{
Client client = EsUtils.getEsClient();
//得到client
//首先创建index
CreateIndexResponse createIndexResponse = client.admin().indices()
.prepareCreate("testindex2").execute().actionGet();
System.out.println("创建不带分词的索引2="+createIndexResponse.isAcknowledged());
PutMappingRequestBuilder mappingRequest = client.admin().indices().preparePutMapping("testindex2").setType("indextype2").setSource(createTestModelMapping2());
PutMappingResponse putMappingResponse = mappingRequest.execute().actionGet();
System.out.println("创建不带分词的索引2putMappingResponse="+putMappingResponse.isAcknowledged());
EsUtils.closeClient();
}
//创建Index2中字段
private XContentBuilder createTestModelMapping2()throws Exception{
XContentBuilder builder = XContentFactory.jsonBuilder().startObject().startObject("indextype2").startObject("properties").startObject("wildcardStr").field("type", "string").field("index", "not_analyzed").field("store", true)
.endObject()
.endObject()
.endObject();
return builder;
}
那么我们的mapping创建好了,现在进行插入数据,数据目前我插入的是3000000的数据进行查询,如图
文章图片
现在我们就可以进行查询了,我先直接使用head插件进行查询,分别对需求中的描述进行查询
- 我们先对“张“这个词进行查询(切记使用wildcard查询的时候千万不要分词)
文章图片
- 我们先对“三“这个词进行查询
文章图片
- 我们先对“张三“这个词进行查询
文章图片
文章图片
重点来了
下面我们来进行一元分词的实现。首先我们继续创建一个索引
/***
* 创建带分词的索引1
*/
@Test
public void creatIndex1() throws Exception{
Client client = EsUtils.getEsClient();
//得到client
//首先创建index
CreateIndexResponse createIndexResponse = client.admin().indices()
.prepareCreate("testindex1").setSettings(createTestIndex1Settings()).execute().actionGet();
System.out.println("创建带分词的索引1="+createIndexResponse.isAcknowledged());
PutMappingRequestBuilder mappingRequest = client.admin().indices().preparePutMapping("testindex1")
.setType("indextype1")
.setSource(createTestModelMapping1());
PutMappingResponse putMappingResponse = mappingRequest.execute().actionGet();
System.out.println("创建带分词的索引1putMappingResponse="+putMappingResponse.isAcknowledged());
EsUtils.closeClient();
}
//创建Index1中的分词settings
private XContentBuilder createTestIndex1Settings() throws Exception{
XContentBuilder settings = XContentFactory.jsonBuilder().startObject()
.startObject("analysis")
.startObject("analyzer")
.startObject("ngramAnalyzer").field("tokenizer", "my_ngramAnalyzer").endObject().endObject()
.startObject("tokenizer")
.startObject("my_ngramAnalyzer").field("type", "ngram").field("min_gram", 1).field("max_gram", 1).field("token_chars", "letter, digit")
.endObject()
.endObject()
.endObject()
.endObject();
return settings;
}
//创建Index1中的字段
private XContentBuilder createTestModelMapping1()throws Exception{
XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
.startObject("indextype1")
.startObject("properties")
.startObject("anlyzerStr").field("type", "string").field("analyzer", "ngramAnalyzer").field("store", true)
.endObject()
.endObject()
.endObject()
.endObject();
return builder;
}
创建成功之后,我们继续看看整个mapping的构造
文章图片
通过上图可以看到我们指定了setting和分词器,ngram是es中自带的分词器,下面我们来进行插入数据
文章图片
插入的数据也是3000000的数据,下面我们来进行查询
文章图片
文章图片
文章图片
通过以上的三张图我们可以看出使用一元分词之后也是可以实现完全匹配的,下面针对查询的速度我做了下对比,如图
文章图片
好了,以上均是使用Elasticsearch全部都能实现的完全匹配模式,最后做出对比之后发现QueryString查询的速度是最快的,仅仅作为个人操作一下特殊的业务做的技术处理,欢迎吐槽。
推荐阅读
- 20170612时间和注意力开销记录
- 【故障公告】周五下午的一次突发故障
- 我要我们在一起(二)
- 洱海不是海,,人群没有你
- 我的拖延症如何控制了我,又一次
- 【剽悍读书营成长记录】2018年我收获了什么|【剽悍读书营成长记录】2018年我收获了什么 3357-小松
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片
- 跟身体谈恋爱
- 课后分享记录
- 记一次赛课失利