Go项目(es搜索-1)
创始人
2024-06-02 06:37:02
0

文章目录

  • 简介
  • 安装
  • 概念
  • kibana
  • 基操
    • _bulk
    • _mget
  • 复杂查询
    • 倒排索引
    • match_phrase
    • multi_match
    • query_string
    • term
    • range
    • fuzzy
    • 复合查询
  • mapping
    • Analyzer
    • Tokenizer
    • IK
  • 小结

简介

  • 使用 elasticsearch 实现搜索功能
  • 直接用 MySQL 搜索的缺点
    • 性能低
    • 没有相关性排名
    • 无法全文搜索
    • 不能分词,搜索不准确
  • 全文搜索
    • 搜索分两类
      • 结构化数据的搜索:对数据库的搜索,用SQL语句;对元数据的搜索,如 Windows 对文件名,类型,修改时间等进行搜索
      • 非结构化数据的搜索:搜索邮件、Word中的内容,Linux下的grep命令,用 Google 和百度搜索大量内容数据
    • 对非结构化数据的搜索也叫全文搜索,主要有两种方式
      • 顺序扫描法:一个文档一个文档的看
      • 全文检索法:先建立索引,再对索引进行搜索;索引是从非结构化数据中提取并组织好的信息
  • Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎
    • 当然,Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作
    • 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索
    • 实时分析的分布式搜索引擎
    • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据
    • 适用场景:电商网站检索商品,Stack Overflow,日志数据分析、logstash采集日志,复杂的数据分析(ELK),BI 系统、商业智能

安装

  • docker 安装 es,避免因为环境出错
    systemctl status firewalld.service
    # 建立一些必要的文件夹,挂载到容器
    mkdir -p /data/elasticsearch/config
    mkdir -p /data/elasticsearch/data
    mkdir -p /data/elasticsearch/plugins
    # chmod 777 -R /data/elasticsearch
    chmod 777 /data/elasticsearch/*
    # 写入配置
    echo "http.host: 0.0.0.0" >> /data/elasticsearch/config/elasticsearch.yml
    # 创建容器,7.10.1即可,内存不需要给太大,服务太多虚拟机带不起来了
    docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
    -e "discovery.type=single-node" \
    -e ES_JAVA_OPTS="-Xms128m -Xmx256m" \
    -v /data/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
    -v /data/elasticsearch/data:/usr/share/elasticsearch/data \
    -v /data/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
    -d elasticsearch:7.10.1
    
  • docker 安装 kibana,相当于 Navicat 对于 MySQL;版本要和 es 对应,用虚拟机 IP,不能使用 127.0.0.1,因为 docker 网络和 host 隔离,容器间访问需要经过 eth0
    docker run -d --name kibana -e ELASTICSEARCH_HOSTS="http://192.168.109.128:9200" -p 5601:5601 kibana:7.10.1
    
  • 访问:http://192.168.109.128:5601/app/home#/
    1
  • 选择 Explore on my own,Dev tools

概念

  • 对比 MySQL 学习 es7
    1
  • 在 es 中,我们说索引一个数据,就是把数据存储到一个或者多个索引中,作为名字时,表示“表”

kibana

  • 使用 kibana 操作 es7
    • 底层是 es 提供的 restful 接口,所以使用 postman 操作也没问题;但是 kibana 更方便
      2
    • kibana 官方文档
  • 查询所有索引,选中部分会出现运行按钮,json语法,块状 { } 会被一起选中
    1
  • PUT 新建数据
    • 在版本 7 之前 type 不是固定的,7 之后都是 _doc,暂时先不用深究
      2
    • result 指明数据已创建
    • 如果再次执行,会是 updated
      3
    • 关于 _version_seq_no 的介绍
  • POST 新建数据
    • 和 PUT 最大的区别是,PUT 必须带 id
    • POST 不带 id,每次运行都会新建,也会随机生成新的 id_version 一直是 1,但同一 index 里, _seq_no 一直在递增
      4
    • 带 id,和 PUT 一样的,第二次运行会更新_version 在变, _seq_no 当然也是增加的
      5
    • 可以简单理解成 version 监视 id 的变化,seq_no 监视 index 的变化(带不带 id 都会在之前的基础上增加,不论之前的操作是什么)
    • 如果我们希望没有就创建,有的话不是更新而是报错呢?使用 _create
      51
  • GET 获取数据
    • 只获取数据,但如果只是这样用 MySQL 就行
      6
    • 一般会用如下两种查询方式,建议看文档学习
      • URI带有查询条件(轻量查询),也可以直接指明 index
        7
      • 请求体中带有查询条件(复杂查询),更常用,后面会重点介绍
      • es 对大小写不敏感,其实是会把大写转为小写
  • POST 更新数据
    • 如果用上面提到的方法更新,会覆盖原有的数据,需要加 _update 配合 doc
      8
    • 重复运行 version 不会变,也就是说,底层会判断是否产生更新
  • DELETE 删除数据
    • 也是用 _doc
      9

基操

  • 上面增删改查是基操中的基操,主要是接受一下相关概念
  • 接下来了解批量操作

_bulk

  • 官方文档
  • 上面写索引和 id ,下面写数据
    1
  • 批量插入一部分数据,没有 error 即可,后面复杂查询会用到
    2
  • 记得先清空一下 index

_mget

  • 批量查询,还是基于 doc,或 docs
    1
  • 规律:
    • body 中,GET 指明查询条件且基于 docs 时,用下划线 _,比如指明索引 _index,指明 id _id;POST 不用下划线
    • URL 中,都要用下划线

复杂查询

  • 复杂查询一般将条件放在请求体中,官方文档,es 提供了 Query-DSL 方式
    • 条件要放在 query match
    • 默认只显示 10 条数据(385个结果)
      1
    • 相当于默认 pageInt = 0,pageSize =10
  • 对于轻量数据可以使用 fromsize 做分页查询,但这类似于 MySQL 的 limit
    2
  • 对于大体量数据,es 提供了很多其他方式,可以查看文档,后面会逐步涉及其中常用的一些方式

倒排索引

  • es 底层使用倒排索引,这个概念非常重要,可以参考学习,这里介绍是因为方便后续理解其他查询方式
    • 建立倒排索引的基本原理如下,核心点是分词
      1
    • 上图中“单词”、“文档”下面说的就是倒排列表,存着倒排索引项;文档就是数据(json 体)
    • 每个倒排索引项中存着文档 ID,这个词的频率,位置,偏移量;下图以 “搜索引擎” 为例
      3
  • es 存储的是 json 格式的文档,包含多个字段,每个字段都有自己的倒排索引
    • 比如我们搜索 address 字段
      2
    • 也会先分词得到 “Madison” 和 “Street”,然后分别到倒排列表中匹配,所以只要包含其中一个词就能匹配上
      3
    • 也就是说,分词后为每个词建立索引,查找时也先分词,用单个单词和索引匹配,效率高

match_phrase

  • 上面说的 query match 是分词后匹配,如果我们想匹配这个词组呢?
  • 这就要用到另一种查询方式 match_phrase
    1
  • 注:这里 GET 就不是基于 doc/docs,不需要 _

multi_match

  • 指定查询多个字段
    1
  • 还可以设定权重,如果我们觉得在 title 中出现比较重要,赋予高权重 ^2
    2

query_string

  • 这种查询方式很灵活,默认匹配所有字段
  • 使用 AND,相当于 match_phrase
    1
  • 使用 OR,类似 multi_match,但是会匹配所有 filed
    2
  • 使用 default_field 指定要查询的字段,类似 match
    3
  • 查询所有 index 的所有数据 match_all
    4
    GET _search
    {"query": {"match_all": {}}
    }
    
  • 以上就是基于 query match 的常用查询方式,属于 Query-DSL,当然,DSL 还包含很多其他查询方式

term

  • term 查询和 match 查询在查单个单词时是等价的,但是 term 不分词,类似 match_phrase
  • 不在查询时分词,又称原子查询,即拿着整个词组做查询,而不是拆分开单独匹配
  • 但是,我们在加入索引时做了分词,拿着词组去和单个词匹配,肯定是查不到的
    1
  • 也不能使用大写字符匹配,因为 term 不会像 match 和加入索引时那样转小写,只能我们直接用小写去匹配
    2
  • 简而言之,term 不做任何处理,这在有些不需要处理查询条件的场景下还是有用的,比如匹配客户姓名
  • 但是这需要在加入索引时就不分词不转换,后续会了解到如何操作
  • 我们可以将一些不需要分词的查询归为一类,也就是归为基于 query term 的方式,属于 Query-DSL

range

  • 归类为 term,范围查询不涉及分词
    1
  • gte 表示大于等于
  • 顺带说一个:exists,查询有某个字段的数据
    2

fuzzy

  • 模糊查询,底层用的算法是计算字符串的编辑距离
    1
  • 当然,match 中也可以开启模糊查询,再使用 query
    2
  • 嵌套查询也可以,注:是 _source 中的嵌套
    3

复合查询

  • 最常用的是 bool 查询,官方文档
  • 有如下可选字段,后两个是基础条件,前两个是加分项
    must: 必须匹配,查询上下⽂,加分,也属于过滤(必须要有),但是影响分数,这要看里面具体条件怎么写了,如果用match这种匹配词组的,分数会不一样
    should: 应该匹配,查询上下⽂,加分(附加分)
    must_not: 必须不匹配,过滤上下⽂,过滤,不影响分数
    filter: 必须匹配,过滤上下⽂,过滤,不影响分数
    
  • 可以使用前面的多种查询方式,这就是 复合 的意思
    1
  • must_not,注意看目前的分数
    2
  • should,加分了;注意要用小写,因为写入索引时转小写了
    3
  • filter,不影响分数
  • 小结一下
    • 写入/更新数据:PUT/POST,用 _doc
    • 轻量查询:URL 中

mapping

  • 相当于数据库的 schema,定义字段名称、类型,字段约束(倒排索引的相关配置等)
  • 核心数据类型可以划分为字符串类型、数字类型、日期类型、布尔类型、基于 BASE64 的二进制类型、范围类型
  • ES 7.x 有两种字符串类型:text 和 keyword;重点关注 keyword
    1
  • address 是 text 类型,但这里相当于 es 多加了一个 keyword type,可以让我们查询不分词的情况
    {"address":{"keyword":"Madison Street"	// keyword 类型"value":"Madison Street"	// text 类型}
    }
    
  • keyword 类型是将整个字符串存入索引(也可能没用索引,这个字段的所有数据直接存),但并不和分词后建立的倒排索引在一起,查询时要指明
    2
  • 测试
    • 先创建索引,注意 desc 字段
      3
    • 写入数据,term 查询,很正常;按之前说的,term 不分词,keyword 字段也没分词
      4
    • match 查询;按之前说的,会先进行分词,但 desc 只有 keyword 类型,倒排索引中没有,那为什么也能查询到呢?
      5
    • 其实这里的 match 没有分词从倒排索引查询,为了更深入理解,先了解一下 Analyzer

Analyzer

  • es 的文本分析是使用 Analyzer 完成的,由三部分组成
    • Character Filters
    • Tokenizer
    • Token Filters
  • Character Filters
    • 字符过滤器接收原始文本text的字符流,可以对原始文本增加、删除字段或者对字符做转换
    • 一个 Analyzer 分析器可以有 0-n 个按顺序执行的字符过滤器
  • Tokenizer
    • 分词器接收Character Filters输出的字符流,将字符流分解成逐个单词,并且输出单词流
    • 例如空格分词器会将文本按照空格分解,将 “Quick brown fox!” 转换成 [Quick, brown, fox!]
    • 分词器也负责记录每个单词的顺序和该单词在原始文本中的起始和结束偏移 offsets
    • 一个 Analyzer 分析器有且只有 1 个分词器
  • Token Filter
    • 单词过滤器接收分词器 Tokenizer 输出的单词流,对单词做增删转换操作
    • 比如 lowercase token filter 负责全部转为小写,stop token filter 会删除 the and 这类词
    • token filter 不能改变单词在原始文本中的偏移量,不然上面白记了
  • 常见 Analyzer
    • Standard Analyzer - 默认分词器,按词切分,小写处理
    • Simple Analyzer - 按照非字母切分(符号被过滤,英文文本就是空格),小写处理
    • Stop Analyzer - 小写处理,停用词过滤(the ,a,is)
    • Whitespace Analyzer - 按照空格切分,不转小写
    • Keyword Analyzer - 不分词,直接将输入当做输出
    • Patter Analyzer - 正则表达式,默认 \W+
    • Language - 提供了 30 多种常见语言的分词器
  • OK,这和上面的问题是什么关系呢?官方文档
    • 分析一下这段话
      1
    • 在查询时,可以指定查询使用的 analyzer,如图,指定 simple,就会安装之前理解的那样,分词,去倒排索引匹配
      2
    • 可以在创建索引时指定字段的存储和查询的 analyzer,官方示例:
      3
    • 还可以在创建索引时在 settings 指定 index 的 analyzer
    • 最后,不同的 type 会有默认的 analyzer,比如 keyword 就是 Keyword Analyzer
    • 如果上述四个都没有指定 analyzer,那就用 Standard Analyzer
  • OK,进一步了解后我们发现,写入和查询的策略都是可以设置的
    • 在写入索引和查询时,都可以指明 analyzer,如果没有指明,就会按照上面的策略
      // 写个例子
      PUT usertest
      {"mappings": {"properties": {"age":{"type": "text","analyzer": "standard"}}}
      }
      
    • 还有哪些地方可以设置呢?有什么影响呢?后续会涉及,settings 还没有介绍
  • 因此,上面的问题中,match 查询为什么没有分词使用倒排索引?因为使用了策略第 4 点,keyword 类型的默认 Keyword Analyzer,它里面的分词策略是:不分词

Tokenizer

  • 分词器,很重要,为什么呢?
  • 先看看中文怎么分词的
    1
  • 默认将每个汉字分为一个词,这肯定是不合理的,分词不恰当,后续的查询就无从谈起
  • NLP 解决问题的思路也是基于分词,将文本(非结构化数据)转化为结构化数据,进而转化为数学问题
  • 词是表达完整意义的最小单位,中英文分词的三个典型区别
    • 分词方式不同,中文更难,英文有天然的空格作为分隔符
    • 英文单词有多种形态,中文则不需要
    • 中文分词需要考虑粒度问题,比如 “中国科学技术大学”,可以分为 “中国/科学技术/大学”,或者 “中国/科学/技术/大学”
  • 三种典型的分词方法
    • 基于词典匹配
      • 速度快、成本低
      • 适应性不强,不同领域效果差异大
    • 基于统计
      • 适应性较强
      • 成本较高,速度较慢
      • HMM、CRF、SVM
    • 基于深度学习(NLP)
      • 准确率高、适应性强
      • 成本高,速度慢
  • 中文分词工具
    • jieba
    • Hanlp
    • IK
  • 英文分词工具
    • Keras
    • Spacy
    • Gensim

IK

  • es 中使用中文分词器 IK,需要和 es 版本对应 http://192.168.109.128:9200/
  • 下载解压到 plugins/ik 目录,进入 es 容器,能看到 ik 插件
    [root@12e0e2f9920d bin]# elasticsearch-plugin list  
    ik
    
  • 修改文件权限 chmod 777 -R ik/
  • 重启容器 docker restart elasticsearch
  • 使用
    • ik_smart
      1
    • ik_max_word,将所有可能的词都列出来
      2
  • 测试
    • 建表,指定分词器;注:准确的说是指定 analyzer,包括了上面说的三个部分(字符过滤器、分词器、单词处理器)
      3
      PUT cn
      {"mappings": {"properties": {"name": {"type":"text","analyzer":"ik_smart","search_analyzer": "ik_smart"}}}
      }
      
    • 但是我们查询数据发现这个分词器是基于字典的,遇到新词或专有名词分的不太好
      4
    • 我们可以添加自己的 dic
      • config 下新建目录 mydic(名称任意),新建文件 test.dic,输入专有名词或新词,换行分割
      • config 下新建 stop_word.dic,输入停用词,比如 “的,嘿,呦” 等
      • 配置词典路径
        5
      • 重启 es 容器
    • 注:我们通过 GET _analyze 能看到分词情况,match 是看不到的,只能显示匹配到的结果,也就是我们 POST 进去的数据,但通过 match 中传入不同的查询字符串都能得到这个结果就可以证明分词是起效的
    • 比如未加入自定义词典时,通过“华”可以查到那条数据,但是自定义词典后就不行了,因为没有把 “华”单独分出来,我们使用 eq 时也就无法匹配上

小结

  • 这一节主要了解了 es 的基本原理和基操,记住一些关键的概念:倒排索引、Query-DSL、分析器、分词器
  • 接下来要将 es 集成到我们的 web 层,开发搜索功能

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...