记录一次elasticsearch模糊匹配

【记录一次elasticsearch模糊匹配】在接触elasticsearch的时候,起初我是想用这个技术对外封装所有的接口,但是有些想法始终不是现实,刚开始接触的时候搜索的确带来速度的快感,所以用这门技术对任何需求进行了CRUD;闲话少说,现在来介绍下使用过程中遇到小问题,需求如下:

  1. 实现如mysql 中的 like查询 %XXXXXX%
  2. 基于elasticsearch实现完全匹配如 like %XXXXXX%
  3. 例如有个字段数据为“张三” 那么必须用 '张' -‘三’-‘张三’等三个词都能查询到对应的数据
下面可以提供两个在线分词进行测试
  • 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的数据进行查询,如图
记录一次elasticsearch模糊匹配
文章图片

现在我们就可以进行查询了,我先直接使用head插件进行查询,分别对需求中的描述进行查询
  • 我们先对“张“这个词进行查询(切记使用wildcard查询的时候千万不要分词)
    记录一次elasticsearch模糊匹配
    文章图片
  • 我们先对“三“这个词进行查询
    记录一次elasticsearch模糊匹配
    文章图片
  • 我们先对“张三“这个词进行查询
    记录一次elasticsearch模糊匹配
    文章图片
下面我们再来测试下WildCard查询的速度,后续我会继续讲解如何选择完全匹配的查询,下面这张图是我对3000000的数据索引进行了10次的WildCardQuery查询的记录
记录一次elasticsearch模糊匹配
文章图片

重点来了
下面我们来进行一元分词的实现。首先我们继续创建一个索引
/*** * 创建带分词的索引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的构造
记录一次elasticsearch模糊匹配
文章图片

通过上图可以看到我们指定了setting和分词器,ngram是es中自带的分词器,下面我们来进行插入数据
记录一次elasticsearch模糊匹配
文章图片

插入的数据也是3000000的数据,下面我们来进行查询
记录一次elasticsearch模糊匹配
文章图片

记录一次elasticsearch模糊匹配
文章图片

记录一次elasticsearch模糊匹配
文章图片

通过以上的三张图我们可以看出使用一元分词之后也是可以实现完全匹配的,下面针对查询的速度我做了下对比,如图
记录一次elasticsearch模糊匹配
文章图片

好了,以上均是使用Elasticsearch全部都能实现的完全匹配模式,最后做出对比之后发现QueryString查询的速度是最快的,仅仅作为个人操作一下特殊的业务做的技术处理,欢迎吐槽。

    推荐阅读