Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略

这篇具有很好参考价值的文章主要介绍了Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、背景

在生产使用中,Elasticsearch 除了精确匹配的要求,也会有模糊查询的场景。

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

2、解决方案探讨

面对这种问题 ,传统的解决方案有两种:

2.1 方案一:ngram 分词器

使用 ngram 分词器对存入的数据进行精细化的拆分,利用细颗粒度的 token 进行快速的召回。

这是一个利用空间换时间的方案,细化查询所需的词根内容,利用精确匹配结果大范围的命中来达到模糊效果。

PUT test-005
{
  "settings": {
    "index.max_ngram_diff": 10,
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_analyzer",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
 
POST test-005/_bulk
{"index":{"_id":1}}
{"title":"英文官网承认刘强东一度被捕的原因是涉嫌性侵"}
{"index":{"_id":2}}
{"title":"别提了朋友哥哥刘强东窗事发了"}
{"index":{"_id":3}}
{"title":"刘强东施效颦,没想到竟然收获了流量"}
{"index":{"_id":4}}
{"title":"刘强东是谁?我不认识"}
 
POST test-005/_search
{
  "query": {
    "match_phrase": {
      "title": "刘强东"
    }
  }
}
  • 优点:召回快,性能消耗小;

  • 缺点:有不小的空间消耗,颗粒度越细,消耗越大。同时,有一定的学习成本,需要对分词器有成熟的了解,不适合新手。

这里有个明显的使用案例,如下图所示,使用 ngram 的 test2 索引比原来使用 keyword 的索引空间大小大了接近10倍。

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

2.2 方案二:wildcard 查询

使用 wildcard 查询,这是一项支持通配符的模糊检索功能,有点类似 SQL 中的 like 匹配。

为了实现通配符和正则表达式的查询,Ealsticsearch 依赖的 Lucene4.0 会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),而带有通配符的pattern构造出来的DFA可能会很复杂,开销很大。

具体分析:

https://elasticsearch.cn/article/171 

https://elasticsearch.cn/article/186

  • 优点:使用简单,也不需要额外的存储资源。

  • 缺点:性能消耗巨大,滥用则可能会造成线上事故。

面对两个各有所长,甚至有点“卧龙凤雏”的方案,ES 在 7.9 版本推出了 wildcard 字段类型来解决模糊匹配的场景需求。

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

3、wildcard 类型使用详解

Elasticsearch 的 wildcard 字段类型最早在 7.9 版本中引入。这个版本加入了对 wildcard 类型的支持,旨在改善模糊匹配的查询效率和性能,特别是在处理大量文本数据时。这一新特性主要针对了之前版本中 wildcard 查询的性能问题,提供了更高效的方式来处理通配符和正则表达式的搜索需求。

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

https://www.elastic.co/guide/en/elasticsearch/reference/7.9/release-highlights.html

我们先来看下 wildcard 类型怎么使用:

先定义一个 wildcard 类型的字段

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_wildcard": {
        "type": "wildcard"
      }
    }
  }
}

为其写入一个文档

PUT my-index-000001/_doc/1
{
  "my_wildcard" : "This string can be quite lengthy"
}

然后使用 wildcard 查询如下所示:

GET my-index-000001/_search
{
  "query": {
    "wildcard": {
      "my_wildcard": "*quite*lengthy"
    }
  }
}

结果为

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 3.8610575,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 3.8610575,
        "_source" : {
          "my_wildcard" : "This string can be quite lengthy"
        }
      }
    ]
  }
}

有时候我们需要忽略大小写,可以在 wildcard 查询使用 case_insensitive 参数。

GET my-index-000001/_search
{
  "query": {
    "wildcard": {
      "my_wildcard": {
        "value": "*Quite*lengthy",
        "case_insensitive": true
      }
    }
  }
}

4、wildcard 原理

关于 wildcard 字段的实现,官方在推出该字段的时候发布了相关的说明:

新的 wildcard 字段使用以下两种数据结构以这种方式自动加速通配符和正则表达式搜索:

  • 字符串中所有3个字符序列的  n-gram 索引。

  • 完整原始文档值的 “二进制 doc value” 存储。第一点,底层还是 ngram 的分词去实现模糊查询的场景,但是这里的 ngram 颗粒度是 3,从功能上满足了模糊查询的需求和保证了 wildcard 查询的高性能。

第二点,使用了 ES 中常见的正排+列存数据存储格式 doc value,在这里一个主要的效果就是在自动查询验证由 n-gram 语法匹配产生匹配候选的同时利用了doc value格式相对较高的压缩比。

5、测试

现在来看下 wildcard 实际的表现。

5.1 空间大小

如下图所示,可以看到使用 wildcard 字段的索引与原索引相差不大。

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

5.2 查询效率

查询dsl keyword类型 wildcard类型
wildcard:”红豆 715ms 71ms
wildcard:”006-612014 633ms 22ms
wildcard:”55 584ms 188ms
wildcard:”11 1359ms 357ms

注:这里省却了索引详细信息,只需知道是同一个索引的比对测试。

综上所述,在模糊搜索字段区分度很低的情况下 如:模糊查询单个数字,此时优化效率rt大概是之前的1/3左右,区分度高的场景rt大概是之前的1/15左右,有明显效果。

6、小结

1.可以说 wildcard 字段类型满足了模糊查询的主要需求,同时也提供了相对较高的查询性能;

2.wildcard 针对于 ngram 分词器有着不小的空间优势。

3.wildcard 虽然有着不小的优势,但是查询效率与数据的区分度有着很强的关联,在一些区分度较低的场景下效率与性能消耗依旧很严重。

4.相比 ES 在精确查询场景优秀的性能表现(即 term keyword 的高效,平稳在毫秒级的返回),wildcard 字段在模糊查询场景下的使用还是需要研发人员根据实际场景测试选择。

7、作者介绍

金多安,Elastic 认证专家,Elastic资深运维工程师,死磕Elasticsearch知识星球嘉宾,星球Top活跃技术专家,搜索客社区日报责任编辑

铭毅天下审稿并做了部分微调。

推荐阅读

  1. 全网首发!从 0 到 1 Elasticsearch 8.X 通关视频

  2. 重磅 | 死磕 Elasticsearch 8.X 方法论认知清单

  3. 如何系统的学习 Elasticsearch ?

  4. 2023,做点事

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

更短时间更快习得更多干货!

和全球 近2000+ Elastic 爱好者一起精进!

Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略,elasticsearch,大数据,搜索引擎,全文检索

比同事抢先一步学习进阶干货!文章来源地址https://www.toymoban.com/news/detail-757601.html

到了这里,关于Elasticsearch 查询革新:探索 Wildcard 类型的高效模糊匹配策略的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Elasticsearch模糊查询

    Elasticsearch模糊查询 不计算相关度评分 前缀搜索匹配的是term,而不是field。即搜索倒排索引 前缀搜索的性能很差 前缀搜索没有缓存 前缀搜索尽可能把前缀长度设置的更长命中索引越少,性能会好 要注意分词器,如果分词器分词了会导致前缀匹配失败.尤其是中文要设置中文分词

    2024年02月12日
    浏览(39)
  • ElasticSearch中文分词和模糊查询

            ElasticSearch是一个一个分布式的实时文档存储,每一个字段都可以被索引与搜索,并且能支持PB级别的结构化或者非结构化数据。早期我们应用的全局搜索是简单的SQL模糊查询,为了分担数据库压力所以用了ES,选择他的原因除了以上几点外,还有其提供的API方式简单

    2024年02月03日
    浏览(49)
  • Springboot 整合ElasticSearch 常用的插入查询,模糊查询,范围查询

    repository.deleteById(id); } catch (Exception ex) { ex.printStackTrace(); return false; } return true; } public Dog saveDog(Dog dog) { try { Dog save = repository.save(dog); System.out.println(“结果:”+save.toString()); return save; } catch (Exception ex) { ex.printStackTrace(); return null; } } public Boolean saveDogAll(List dogsList) { try { reposit

    2024年04月22日
    浏览(43)
  • Java实战:SpringBoot+ElasticSearch 实现模糊查询

    本文将详细介绍如何使用SpringBoot整合ElasticSearch,实现模糊查询、批量CRUD、排序、分页和高亮功能。我们将深入探讨ElasticSearch的相关概念和技术细节,以及如何使用SpringData Elasticsearch库简化开发过程。 ElasticSearch是一个基于Lucene构建的开源搜索引擎,它提供了一个分布式、多

    2024年04月25日
    浏览(35)
  • ElasticSearch支持根据英文或者数字进行模糊查询

    提示:以下操作均在kibana7.7.0中操作。 根据es去查询商品的名称,中文查询能查询出数据,但是只输入部分英文或者数字,查询不出数据。 es中的分词器,只将全部的数字和英文做了分词,即将他们看成一个单词,所以,只输入部分英文或者数字时,不存在该部分的分词,估

    2024年02月12日
    浏览(49)
  • Elasticsearch 中基于wildcardQuery的模糊查询失效

    es中常用的模糊查询为: \\\"query\\\": {         \\\"wildcard\\\": {             \\\"testWord\\\": \\\"*测试数据*\\\"         }     } 对应java中es的API为:  一般情况下,这个模糊查询是没有问题的,但是当testWord的字段过长时,会导致es搜索失效。通过资料查询,这个文本的范围在256~32

    2024年02月05日
    浏览(37)
  • Elasticsearch:使用 query_string 查询的短语及模糊查询

    在我之前的文章系列里,我详细描述了 query_string 的一些功能: Elasticsearch: query_string 查询 Elasticsearch:以更简单的方式编写具有逻辑条件的 Elasticsearch 查询 - query_string Elasticsearch:理解 query_string 和 simple_query_string 查询 在今天的文章中,我们来聊聊 query_string 中的一下特殊查询

    2024年02月09日
    浏览(45)
  • Elasticsearch实现对同一字段既能精准查询也能模糊查询

     使用@MultiField注解给字段取别名并设置为keyword类型 dao层如下 实体类如下 模糊查询测试如下: 可以看到模糊查询content中一共有3条数据有我这个分词  精准查询如下:  可以看到精准查询就只有一条结果,符合精准查询。 注意:该方法需要版本支持,具体版本未知,但是在

    2024年02月02日
    浏览(44)
  • elasticSearch7版本文档中文属性模糊查询不准确

    1、问题:es文档中的某个属性值name的值如下所示 name\\\":\\\"catalog=Catalog(value=699015935012372480, displayName=/默认分组), status=3, updaterName=admin, updateTime=2023-02-01 14:33:17)status:已发布” 通过java模糊查询的api(QueryBuilders.fuzzyQuery)查询name为“已”的时候可以查询,查询为“已发布”的时候查

    2024年02月02日
    浏览(51)
  • Elasticsearch - 聚合获取原始数据并分页&排序&模糊查询

    ES版本: 7.6. 需要按照主机ID 进行告警时间的汇总,并且还得把主机相关的信息展示出来。 注: 所有的数据都存在索引中, 通过一个DSL查询展示 实际上就是将terms聚合的结果以列表形式分页展示。 bucket_sort中 from不是pageNum,如想实现pageNum效果,from=pageNum*size即可; terms聚合

    2024年02月05日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包