Elasticsearch模糊查询

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

Elasticsearch模糊查询

前缀查询原理

不计算相关度评分

前缀搜索匹配的是term,而不是field。即搜索倒排索引

前缀搜索的性能很差

前缀搜索没有缓存

前缀搜索尽可能把前缀长度设置的更长命中索引越少,性能会好

要注意分词器,如果分词器分词了会导致前缀匹配失败.尤其是中文要设置中文分词器

前缀索引示例

// 创建prefix索引; 索引最大最小长度
//含义:对词项继续创建倒排索引. 指的是比如一个词Elasticsearch, el建一个倒排索引,ela再建一个,根据你的min和max; 索引的基础上继续创建索引,浪费空间,提高性能;

前缀索引要注意分词;


##没有分词的前缀索引查询
POST /my_index1/_bulk?filter_path=items.*.error
{"index":{"_id":"1"}} 
{"text":"城管打电话喊商贩去摆摊摊"} 
{"index":{"_id":"2"}} 
{"text":"笑果文化回应商贩老农去摆摊"} 
{"index":{"_id":"3"}} 
{"text":"老农耗时17年种出椅子树"} 
{"index":{"_id":"4"}} 
{"text":"夫妻结婚30多年AA制,被城管抓"} 
{"index":{"_id":"5"}} 
{"text":"黑人见义勇为阻止抢劫反被铐住"}
GET my_index1/_search
{
  "query": {
    "prefix": {
      "text": {
        "value": "城管"
      }
    }
  }
}


##有中文分词的前缀索引
##filter_path=items.*.error 这个表示只显示错误信息
##设置mapping 先把mapping模板查出来
DELETE my_index2
GET my_index2/_mapping
PUT my_index2
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "ik_max_word",
        // 创建prefix索引; 索引最大最小长度
        //含义:对词项继续创建倒排索引. 指的是比如一个词Elasticsearch, el建一个倒排索引,ela再建一个,根据你的min和max; 索引的基础上继续创建索引,浪费空间,提高性能; 
        "index_prefixes": {
          "min_chars":2,
          "max_chars":4
        },
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}
POST /my_index2/_bulk?filter_path=items.*.error
{"index":{"_id":"1"}} 
{"text":"城管打电话喊商贩去摆摊摊"} 
{"index":{"_id":"2"}} 
{"text":"笑果文化回应商贩老农去摆摊"} 
{"index":{"_id":"3"}} 
{"text":"老农耗时17年种出椅子树"} 
{"index":{"_id":"4"}} 
{"text":"夫妻结婚30多年AA制,被城管抓"} 
{"index":{"_id":"5"}} 
{"text":"黑人见义勇为阻止抢劫反被铐住"}
GET my_index2/_search
GET my_index2/_search
{
  "query": {
    "prefix": {
      "text": {
        "value": "城管"
      }
    }
  }
}

通配符 willward

通配符也匹配的是term

##英文通配符数据
POST /product_en/_bulk?filter_path=iterm.*.error
{"index":{"_id":"1"}}
{"title":"my english","desc":"shouji zhong de zhandouji","price":3999,"tags":["xingjiabi","fashao","buka","1"]}
{"index":{"_id":"2"}}
{"title":"xiaomi nfc phone","desc":"zhichi quangongneng nfc,shouji zhong de jianjiji","price":4999,"tags":["xingjiabi","fashao","gongjiaoka","asd2fgas"]}
{"index":{"_id":"3"}}
{"title":"nfc phone","desc":"shouji zhong de hongzhaji","price":2999,"tags":["xingjiabi","fashao","menjinka","as345"]}
{"title":{"_id":"4"}}
{"text":"xiaomi erji","desc":"erji zhong de huangmenji","price":999,"tags":["low","bufangshui","yinzhicha","4dsg"]}
{"index":{"_id":"5"}}
{"title":"hongmi erji","desc":"erji zhong de kendeji","price":399,"tags":["lowbee","xuhangduan","zhiliangx","sdg5"]}

GET product_en/_search
{
  "query": {
    "wildcard": {
      // 加keyword和不加是有区别
      "title.keyword": {
        "value": "nfc*"
      }
    }
  }
}

上边代码加keyword和不加是有区别的, keyword是不会分词的,field是会分词的

正则

flags

指的是允许使用正则表达式中哪些通配符

ALL

启用所有可选操作符。

COMPLEMENT

启用操作符。可以使用对下面最短的模式进行否定。例如

a~bc # matches 'adc' and 'aec' but not 'abc'

INTERVAL

启用<>操作符。可以使用<>匹配数值范围。例如

foo<1-100> # matches 'foo1', 'foo2' ... 'foo99', 'foo100'
foo<01-100> # matches 'foo01', 'foo02' ... 'foo99', 'foo100'

INTERSECTION

启用&操作符,它充当AND操作符。如果左边和右边的模式都匹配,则匹配成功。例如:

aaa.+&.+bbb # matches 'aaabbb'

ANYSTRING

启用@操作符。您可以使用@来匹配任何整个字符串。
您可以将@操作符与&和~操作符组合起来,创建一个“everything except”逻辑。例如:

@&~(abc.+) # matches everything except terms beginning with 'abc'

模糊查询

主要是解决你输入错误能智能纠错的功能,本质也是模糊查询

常见的如:

缺少字符/多字符/混淆字符(输入错了)/顺序颠倒

语法

GET <index>/_search
{
  "query": {
    "fuzzy": {
      "<field>": {
        "value": "<keyword>"
      }
    }
  }
}

value必输项

数据实测

比如你有如下数据:

    "hits" : [
      {
        "_index" : "product_en",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.8829135,
        "_source" : {
          "title" : "xiaomi nfc phone",
          "desc" : "zhichi quangongneng nfc,shouji zhong de jianjiji",
          "price" : 4999,
          "tags" : [
            "xingjiabi",
            "fashao",
            "gongjiaoka",
            "asd2fgas"
          ]
        }
      }
    ]

以下查询 都可以查出数据

GET product_en/_search
{
  "query": {
    "fuzzy": {
      "title": {
        //         "value": "xiaoi"
        //         "value": "mixiao"
        // "ixaomi"
        "value": "xiaohi"
      }
    }
  }
}

召回率优化

根据以上原理我们知道, 输入错误的数量是有限制的. 那么哪里限制的? 怎么修改? 设置多少合适呢

我们输入错几个字符可以匹配呢?

把错误的字符修正成正确需要的步骤数量,称为编辑距离. 这距离计算跟特定的计算公式有关系:

两段文本之间的Damerau-Levenshtein距离是使一个字符串与另一个字符串匹配所需的插入、删除、替换和调换的数量
距离公式:lucene使用Levenshtein算法,es使用改进版Damerau-Levenshtein,
如axe=>aex不同算法需要步骤: Levenshtein=2 Damerau-Levenshtein=1

这个距离越大允许错的字符就越多.

但是这个距离并非越大越好,越大召回率越高,但是召回率高不代表准确,也许更不准确了.

ES默认的编辑距离编辑距离,(0,1,2)

模糊查询的几个参数

value: 必须,关键词

fuzziness: 可选,定义编辑距离,es默认(0,1,2);可以设置"AUTO",es会根据字符串长度动态的取值.

transpositions:(可选,布尔值)指示编辑是否包括两个相邻字符的变位(ab→ba)。默认为true。影响某些编辑距离的计算结果.true的话是改进版对换距离为1,如果false就变为2了.

GET product_en/_search
{
  "query": {
    "fuzzy": {
      "title": {
        "value": "ixaomi",
        //"fuzziness": "AUTO"
        "fuzziness": 5
      }
    }
  }
}

match_phase

性能差

基本要求

  • match phase会被分词
  • 匹配要求: 搜索词和源数据的分词顺序一致; 中间不能又其他词

匹配原理

允许搜索词最后一个词项作为前缀再次检索

匹配流程:

最后一个词项作为前缀,匹配所有词->再使用搜索词剩余前缀再次前缀匹配

整个过程比较耗费性能的.

示例

abc cde fg比如用这个词作为短语匹配的搜索词,它首先找以fg开头的满足的所有词项,在这些词项中再去匹配abc cde开头的.

match_phrase_prefix与match_phrase

match_phrase_prefix与match_phrase相同,但是它多了一个特性,就是它允许在文本的最后一个词项(term)上的前缀匹配,

如果是一个单词,比如a,它会匹配文档字段所有以a开头的文档;

如果是一个短语,比如 “it is horse” ,他会先在倒排索引中做以horse做前缀搜索,然后在匹配到的doc中做match_phrase查询

性能调优

如何避免匹配词过多呢?

可以使用max_expentions.这个参数默认值是50

这里尤其要注意max_expentions=1时并不代表实际返回结果就是1个. 这里的1每个分片限制的数量, 如果有多个分片的话每个分片都可能匹配到一个(如果匹配不到就没办法了)

词序颠倒召回率调优

使用参数slop

测试脚本




GET product_en/_search
{
  "query": {
    "match_phrase": {
      "desc": "shouji zhong de"
    }
  }
}

GET product_en/_search
##test expansions
##验证虽然max_expansions=1但是依然返回了多个结果
GET product_en/_search
{
  "query": {
    "match_phrase_prefix": {
      "desc": {
        "query": "shouji zhong",
        "max_expansions": 1
      }
    }
  }
}


##test slop
##
GET product_en/_search
{
  "query": {
    "match_phrase_prefix": {
      "desc": {
        //源数据"shouji zhong de hongzhaji",搜索词:"shouji hongzhaji"时slop=2是可以的slop=1就不行了
        //除了上面间隔词项,顺序颠倒也可以的,搜索词:"de zhong hongzhaji"
        "query": "de zhong shouji hongzhaji",
        "max_expansions": 50
        ,"slop": 5
      }
    }
  }
}

ngram & edge-ngram

可以用作切词方式

ngram是按照字符进行切词

根据如下代码查看效果:

GET _analyze
{
  "tokenizer": "ngram",
  "text": ["abc def opq"]
}

具体怎么切词可以通过min_gram max_gram来控制

作为过滤器

##也可以过滤器
GET _analyze
{
  "tokenizer": "standard",
  "filter": ["ngram"], 
  "text": ["abc def opq"]
}

一个分析器包含

  • 字符过滤器(Character Filters):用于在分词之前对原始文本进行预处理,如HTML标签的去除、字符替换等。
  • 分词器(Tokenizer):将原始文本按照一定的规则进行切分,生成词条(Terms)。常见的分词器有标准分词器(Standard Tokenizer)、简单分词器(Simple Tokenizer)、正则表达式分词器(Pattern Tokenizer)等。
  • 词条过滤器(Token Filters):对切分后的词条进行进一步处理,如小写转换、去除停用词、词干提取等。
  • 字符映射过滤器(Character Mapping Filter):用于字符的映射转换,如大小写转换、字符替换等。

ngram代码测试

##test data
POST /test_idx_001/_bulk 
{ "index": { "_id": "1"} } 
{ "text": "my english" } 
{ "index": { "_id": "2"} } 
{ "text": "my english is good" } 
{ "index": { "_id": "3"} } 
{ "text": "my chinese is good" } 
{ "index": { "_id": "4"} } 
{ "text": "my japanese is nice" } 
{ "index": { "_id": "5"} } 
{ "text": "my disk is full" }

DELETE test_idx_001
PUT test_idx_001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer":{
          "type": "custom",
          "tokenizer":"standard",
          "filter": "my_filter_ngram"
        }
      },
      "tokenizer": {},
      "filter": {
        "my_filter_ngram":{
          "type": "ngram",
          "min_gram":2,
          "max_gram":3
        }
      },
      "char_filter": {}
    }
  },
  "mappings": {
    "properties": {
      "myproperties":{
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

测试ngram个数

##test data
POST /test_idx_001/_bulk 
{ "index": { "_id": "1"} } 
{ "text": "my english" } 
{ "index": { "_id": "2"} } 
{ "text": "my english is good" } 
{ "index": { "_id": "3"} } 
{ "text": "my chinese is good" } 
{ "index": { "_id": "4"} } 
{ "text": "my japanese is nice" } 
{ "index": { "_id": "5"} } 
{ "text": "my disk is full" }

DELETE test_idx_001
PUT test_idx_001
{
  "settings": {
    "analysis": {
      "filter": {
        "my_filter_ngram": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 3
        }
      },
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": "my_filter_ngram"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

GET test_idx_001/_search
GET test_idx_001/_search
{
  "query": {
    "match_phrase": {
      //这里的每个词项必须在2,3范围内因为分词就是按照这个数量分词的,这数量是在上面定义的
      //比如你输入engl就查不到数据了
      "text": "my eng is goo"
    }
  }
}

ngram如果设置的过小会占用大量的磁盘空间,因为它会创建很多倒排索引

edge-ngram测试

edge-ngram会节省空间

edge与ngram的区别在于它只对前N个字母生成索引.具体:

比如my english 我们设置min_gram=2;max_gram=3; 它只会对my eng进行索引;

ngram会对my, my空格, 空格e, 空格en, eng,…等等依次做索引

即ngram不仅前缀,还可以中缀搜索文章来源地址https://www.toymoban.com/news/detail-533098.html

DELETE test_idx_001
PUT test_idx_001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer":{
          "type": "custom",
          "tokenizer": "standard",
          "filter": "myfitler"
        }
      },
      "filter": {
        "myfitler":{
          "type":"edge_ngram",
          "min_gram": 2,
          "max_gram": 3
        }
      },
      "tokenizer": {}
    }
  },
  "mappings": {
    "properties": {
      "text":{
        "type": "text", 
        "analyzer": "my_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}
GET test_idx_001/_search
{
  "query": {
    "match_phrase": {
      "text": "my eng"
    }
  }
}

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

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

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

相关文章

  • 如何使用ES做简单的时间条件过滤+模糊查询+精确匹配+关键字排除,查询 elasticsearch查询结果包含或排除某些字段、_source查询出需要的属性名称

    目录 一、时间条件过滤+模糊查询+精确匹配+排除 1. 查询出包含 log_geo 的数据 “wildcard”: { “message”: “log_geo” } 2. 查询某个时间段的数据 3. 条件查询与条件排除数据 4. from 表示起始的记录的ID 5. size 表示显示的记录数 6.sort排序 desc降序、asc升序  7.should查询在mysql中

    2024年01月18日
    浏览(13)
  • Elasticsearch (ES) 搜索引擎: 数据类型、动态映射、多类型(子字段)

    原文链接:https://xiets.blog.csdn.net/article/details/132348634 版权声明:原创文章禁止转载 专栏目录:Elasticsearch 专栏(总目录) ES 映射字段的 数据类型 ,官网文档参考:Field data types。 下面是 ES 常用的一些基本数据类型。 字符串 类型: keyword :类型。 text :文本类型。

    2024年03月23日
    浏览(20)
  • ElasticSearch中实现模糊查询效果(类似数据库中like功能)

    场景: 业务要求提供一个es查询功能,实现类似模糊查询效果,并且命中字段显示红色。举例说明: es中字段内容 输入(即) 是否输出 你好,中国,强大的祖国 中国 是(则‘中国’两个字飘红) 你好,中国,强大的祖国 俄国 否 你好,中国,强大的祖国 最大 否 实

    2024年02月12日
    浏览(54)
  • ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查

            本篇是这个系列的最后一篇了,在这之前可以先看看前面的内容: ES搜索引擎入门+最佳实践(一)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(二)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(三)_flame.liu的博客-CSDN博客 ES搜索引擎入门+最佳实践(四)_flame.liu的博客

    2024年02月12日
    浏览(14)
  • Java SpringBoot API 实现ES(Elasticsearch)搜索引擎的一系列操作(超详细)(模拟数据库操作)

    Java SpringBoot API 实现ES(Elasticsearch)搜索引擎的一系列操作(超详细)(模拟数据库操作)

    小编使用的是elasticsearch-7.3.2 基础说明: 启动:进入elasticsearch-7.3.2/bin目录,双击elasticsearch.bat进行启动,当出现一下界面说明,启动成功。也可以访问http://localhost:9200/ 启动ES管理:进入elasticsearch-head-master文件夹,然后进入cmd命令界面,输入npm run start 即可启动。访问http

    2024年02月04日
    浏览(16)
  • 使用Logstash同步mysql数据到Elasticsearch(亲自踩坑)_将mysql中的数据导入es搜索引擎利用logstash(1)

    使用Logstash同步mysql数据到Elasticsearch(亲自踩坑)_将mysql中的数据导入es搜索引擎利用logstash(1)

    先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新大数据全套学习资料》,

    2024年04月28日
    浏览(14)
  • Elasticsearch ES操作:查询数据(全部、分页、单条)

    查询 条件查询 指定条数 返回结果

    2024年02月16日
    浏览(12)
  • Elasticsearch模糊查询

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

    2024年02月12日
    浏览(9)
  • 用elasticsearch head查询和删除es数据

    用elasticsearch head查询和删除es数据

    下图中的构成为 http://ip:port/ 索引名/索引类型/_search 请求方式为GET 这种方式是查询该索引下的所有数据 如果要查询更为详细,可以在查询条件后面跟ID,比如 http://ip:port/ 索引名/索引类型名/文档id 请求方式仍然是GET请求 如下图所示 下图是删除指定es下某一文档,其构成为

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

    ElasticSearch中文分词和模糊查询

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

    2024年02月03日
    浏览(13)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包