29、Elasticsearch进阶查询

一、ES查询原理

1 - 官方文档参考

  • es中的分页查询:对于es来说,from和size分页在数据量比较小的情况下可行;如果数据量比较大就要使用scroll
GET user/_search
{
  "query": {
    "match_all": {}
  },
  "from": 4,
  "size": 4
}

在这里插入图片描述

在这里插入图片描述

2 - 倒排索引

在这里插入图片描述

3 - es的搜索过程

在这里插入图片描述


二、全文查询

1 - match查询

  • match查询
    • 模糊匹配,需要指定字段名,但是输入会进行分词,比如“hello world”会进行拆分为hello和world,然后匹配,如果字段中包含hello或world,或者都包含的结果都会被查询出来;
    • 并且大小写不敏感,也就是说match是一个部分匹配的模糊查询
GET user/_search
{
  "query": {
    "match": {
      "address": "street"
    }
  }
}

在这里插入图片描述

2 - match_phrase查询

  • match_phrase:短语查询
    • 会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样
    • 以“hello world”为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的
    • “hello that world”则不满足,world hello也不满足条件
GET user/_search
{
  "query": {
    "match_phrase": {
      "address": "Madison Street"
    }
  }
}

在这里插入图片描述

3 - multi_match查询

  • multi_match:提供了一个简便的方法用来对多个字段执行相同的查询,即对指定的多个字段进行match查询
  • 我们插入一些测试数据
POST resume/_doc/12
{
  "title":"后端工程师",
  "desc":"多年go语言开发经验,熟悉go的基本语法",
  "want_learn":"python语言"
}

POST resume/_doc/13
{
  "title":"go工程师",
  "desc":"多年开发经验",
  "want_learn":"java语言"
}

POST resume/_doc/14
{
  "title":"工程师",
  "desc":"go多年开发经验",
  "want_learn":"java语言"
}
  • 搜索title和desc包含go的数据
GET resume/_search
{
  "query": {
    "multi_match": {
      "query": "go",
      "fields": ["title","desc"]
    }
  }
}

在这里插入图片描述

  • 权重设置:我们希望title中出现go的时候得分更高,注意前面的查询13的得分是0.98,修改title的权重后,得分为1.96
GET resume/_search
{
  "query": {
    "multi_match": {
      "query": "go",
      "fields": ["title^2","desc"]
    }
  }
}

在这里插入图片描述

4 - query_string查询

  • query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛
  • query_string简单查询
GET user/_search
{
  "query": {
    "query_string": {
      "query": "Madison Street"
    }
  }
}

在这里插入图片描述

  • query_string带连接符查询:OR、AND;注意连接符OR和AND不属于查询内容的一部分
    在这里插入图片描述

在这里插入图片描述


三、term级别查询

1 - term查询

  • term查询概念
    • term查询不会进行分词;所有的搜索条件都不会进行分词
    • 如果查询单个单词hello,那么term查询和match查询结果是一样的;
    • 如果查询的是“hello world”,结果就差别很大了
  • term分词的影响
    • 因为term不会分词不会转换成小写,这就导致了如果使用大写的Madison是无法搜索到结果的;
    • 因为数据插入es的时候有分词并全部转换成了小写
      在这里插入图片描述
      在这里插入图片描述

2 - range范围查询

  • 查询年龄在20-30岁之间的用户
GET user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20,
        "lte": 30
      }
    }
  }
}

在这里插入图片描述

3 - exists查询

#插入一条测试数据
POST user/_doc
{
  "school":"middle school"
}

#查询所有有school字段的数据
GET user/_search
{
  "query": {
    "exists": {
      "field": "school"
    }
  }
}

在这里插入图片描述

4 - Fuzzy query查询

  • Fuzzy query概念:返回包含与搜索词相似的词的文档,这些词是由Levenshtein编辑距离度量的
  • 编辑距离:将一个术语转换为另一个术语所需的一个字符的更改次数

在这里插入图片描述

  • match也可以实现模糊查询
#match中使用模糊匹配
#每个分词都会进行模糊匹配
GET user/_search
{
  "query": {
    "match": {
      "address":{
        "query": "Midison streat",
        "fuzziness": 1
      }
    }
  }
}

在这里插入图片描述
在这里插入图片描述


四、复合查询

  • bool查询:复合查询方法比较多,我们主要使用bool查询;must和should会影响得分,而must not和filter不会影响得分主要用来过滤数据;bool查询采用了一种匹配越多越好的方法,因此每个匹配的must或should子句的分数被加在一起,以提供每个文档的最终得分
    • must:必须匹配,表示查询条件必须全部满足
    • should:应该匹配,表示查询条件满足也可以,不满足也可以(满足的得分会高一些)
    • must not:必须不匹配,表示查询条件必须全部不满足
    • filter:必须匹配,过滤上下文,进行过滤
{
  "query": {
    "bool": {
      "must": [
      ],
      "should": [
      ],
      "must_not": [
      ],
      "filter": [
      ],
    }
  }
}
  • bool查询示例
GET user/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
              "state": "tn"
          }
        },
        {
          "range": {
            "age": {
              "gte": 20,
              "lte": 30
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "gender": "m"
          }
        }
      ],
      "should": [
        {
          "match": {
            "firstname": "Decker"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "age": {
              "gte": 25,
              "lte": 30
            }
          }
        }
      ]
    }
  }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


五、mapping

1 - keyword

  • 什么是mapping
    • mapping类似于数据库中的表结构定义schema;
    • mapping在es中用于定义索引中的字段的名称定义字段的数据类型,比如字符串、数字、布尔、倒排索引的相关配置,比如设置某个字段为不被索引、记录position等;
    • 在es早期版本,一个索引下是可以有多个type,从7.0开始,一个索引只有一个type,也可以说一个type有一个mapping定义
      在这里插入图片描述
  • 带keyword查询
    在这里插入图片描述
  • 自定义类型
PUT usertest
{
  "mappings": {
    "properties": {
      "age":{
        "type": "integer"
      },
      "name":{
        "type": "text"
      },
      "desc":{
        "type": "keyword"
      }
    }
  }
}

在这里插入图片描述

2 - match查询原理

  • 我们来查看如下的场景:为什么match查询keyword的desc,可以查询到结果
    在这里插入图片描述

六、分析器Analyzer

1 - analyzer分类

  • analyzer由三部分组成
    • ①.Character Filter(字符过滤器):Character Filter字符过滤器接收原始的输入文本,对字符序列进行过滤(如去掉HTML标签,转换阿拉伯数字等);一个analyzer分析器可以有0或n个按顺序执行的字符过滤器
    • ②.Tokenizer(分词器):将经过处理的文本流分解/分词为单个令牌/术语(token, term, word);标记器也要记录每个term的顺序/位置,以及该术语所表示的原始单词的开始和结束字符偏移量。一个analyzer分析器有且只有一个分词器
    • ③.Token Filters(词条过滤器):词条过滤器接收词条流,并可以对通过的词条进行增删改(如:将词条转小写,删除停止词,引入同义词条等);词条过滤器不可以更改每个词条的位置或字符偏移量;一个analyzer分析器可以有0或n个按顺序执行的单词过滤器
  • Elasticsearch内置的分词器
    在这里插入图片描述
  • Standard Analyzer
GET _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Simple Analyzer:按照非字母切分,非字母则会被去除;小写处理
GET _analyze
{
  "analyzer": "simple",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Stop Analyzer:小写处理;停用词过滤(the,a,is)
GET _analyze
{
  "analyzer": "stop",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Whitespace Analyzer:按空格切分(注意没有大写转小写)
GET _analyze
{
  "analyzer": "whitespace",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Keyword Analyzer:不分词,当成一整个term输出
GET _analyze
{
  "analyzer": "keyword",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Patter Analyzer:通过正则表达式进行分词;默认是\W+(非字母进行分隔)
GET _analyze
{
  "analyzer": "pattern",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

  • Language Analyzer:语言分析器;中文分词要比英文分词要难,英文都以空格分隔,中文理解通常需要上下文理解才能有正确的理解,比如“苹果,不大好吃”和“苹果,不大,好吃”,这两句意思完全不一样
GET _analyze
{
  "analyzer": "english",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

2 - 存数据指定Analyzer

  • 指定Analyzer
    在这里插入图片描述
  • 查询也可以指定Analyzer
GET usertest/_search
{
  "query": {
    "match": {
      "desc":{
        "query": "671 Bristol Street",
        "analyzer": "keyword"
      }
    }
  }
}

在这里插入图片描述

3 - Analyzer顺序


七、分词

1 - 分词的重要性

POST cn/_doc
{
  "name":"中华牙膏"
}

GET cn/_search
{
  "query": {
    "match": {
      "name": "中立"
    }
  }
}

GET _analyze
{
  "text": "中华牙膏"
}

在这里插入图片描述
在这里插入图片描述

2 - 分词的意义

  • 将复杂问题转换为数学问题:机器学习中NLP就是如此,文本都是一些【非结构化数据】,先将这些数据转化为【结构化数据】,结构化数据就可以转换为【数学问题】,而分词就是转化的第一步
  • 词是一个比较合适的粒度
    • 词是表达完整含义的最小单位;
    • 字的粒度太小,无法表达完整含义,如“鼠”可以是“老鼠”也可以是“鼠标”;
    • 而句的粒度太大,承载的信息量多,很难复用,比如“传统方法要分词,一个重要原因是传统方法对远距离依赖的建模能力较弱”
      在这里插入图片描述
  • 中文分词工具:根据github上的star排名
    • jieba
    • Hanlp
    • IK
    • Stanford分词
    • ansj 分词器
    • 哈工大 LTP
    • KCWS分词器
    • 清华大学THULAC
    • ICTCLAS
  • 英文分词工具
    • Keras
    • Spacy
    • Gensim
    • NLTk

3 - IK分词器安装与配置

GET _analyze
{
  "text": "中华牙膏",
  "analyzer": "ik_smart"
}

在这里插入图片描述

  • ik_max_word:将所有分词的可能都列举出来
GET _analyze
{
  "text": "中国科学技术大学",
  "analyzer": "ik_max_word"
}

在这里插入图片描述
在这里插入图片描述

4 - 自定义分词器词库

  • 如果我们希望“好网不”在分词的不被分开如何解决?
GET _analyze
{
  "text": "好网不的课程",
  "analyzer": "ik_smart"
}

在这里插入图片描述

  • ik定义的词库位置
    在这里插入图片描述
  • 我们自定义词库

在这里插入图片描述

  • mydic.dic:添加“好网不”、“中华牙膏”
  • extra_stopword.dic:“的”、“是”、“哟”
  • 添加自定义词库到ik中

在这里插入图片描述
在这里插入图片描述

  • 重启ES容器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无休止符

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值