• 22-07-26 西安 ElasticSearch(01)


    ElasticSearch简介

    Elaticsearch,简称为es,可以看成一个数据库,可以存储数据、搜索数据

    1. es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据
    2. 本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据,1PB=1024TB
    3. es也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能
    4. 但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单

    全文检索

    1.结构化数据与非结构化数据

    • 结构化数据:指具有固定格式或有限长度的数据,如数据库sql【结构化查询语言】,元数据等。
    • 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件

    将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

    数据库中的数据存储是有规律的,有行有列而且数据格式、数据长度都是固定的,所以 数据库搜索很容易


    2.全文检索的实现流程

    先建立索引,再对索引进行搜索的过程就叫全文检索。

    • 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
    • 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

    虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的


    3.倒排索引结构 --面向词汇

    索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。

    正常:先找文档,再在文件内容中匹配搜索关键字
    倒排索引:根据内容(词语)锁定文档。

    倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大


    4.Elasticsearch与mysql的区别

    ElasticSearch和MySql分工不同,MySQL负责存储数据,ElasticSearch负责搜索数据。

    1. 数据库响应时间不可接受(企业级)
    2. 数据库不支持分词
    3. 数据库不支持相关性搜索(行为分析)

    ElasticSearch安装与启动

    1.安装ElasticSearch服务

    学习的是ElasticSearch的Java客户端的使用,安装较为简便的Window版本

    1.1解压elasticsearch-7.8.0-windows-x86_64.zip到 英文且没有空格的目录

    1.2安装IK分词器插件:在plugin目录下创建ik文件夹,将elasticsearch-analysis-ik-7.8.0.zip内容解压到ik目录下

     1.3启动es服务,双击bin目录下的elasticsearch.bat

    1.4 通过浏览器访问ElasticSearch服务器:http://localhost:9200  

    2.安装ElasticSearch客户端

    2.1Postman做ES客户端(废弃不用)


    2.2Kibana客户端(Windows版)

    2.2.1、解压kibana-7.8.0-windows-x86_64.zip

    2.2.2、进入config目录修改kibana.yml第2、28行,配置自身端口和连接的ES服务器地址。

    2.2.3、进入kibana的bin目录,双击kibana.bat启动

    2.2.4、访问:http://localhost:5601


    2.3Elasticsearch head客户端

    ElasticSearch-head-Chrome-0.1.5-Crx4Chrome.crx用压缩工具解压,打开Chrome扩展程序


    啥也不是但很重要系列

    1、 IK分词器

    IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包

    1)采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。
    2)采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。
    3)对中英联合支持不是很好,在这方面的处理比较麻烦.需再做一次查询,同时是支持个人词条的优化的词典存储,更小的内存占用。
    4)支持用户词典扩展定义。

    在没有使用IK分词器时,默认是standard方式分词,这种方式分词就是一个字就是一个词

    IK分词器的俩种模式

    ik_max_word

    会将“乒乓球明年总冠军”拆分为:乒乓球、乒乓、球、明年、总冠军、冠军【可将下面代码运行在

    http://localhost:5601/app/kibana#/dev_tools/console

    1. #方式一ik_max_word
    2. GET /_analyze
    3. {
    4. "analyzer": "ik_max_word",
    5. "text": "乒乓球明年总冠军"
    6. }

    ik_smart(粗粒度分词)
    将“乒乓球明年总冠军”拆分为乒乓球、明年、总冠军

    可运行在这个里测试; http://localhost:5601/app/kibana#/dev_tools/console

    1. #方式二ik_smart
    2. GET /_analyze
    3. {
    4. "analyzer": "ik_smart",
    5. "text": "乒乓球明年总冠军"
    6. }

    2、Elasticsearch核心概念

    Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式

    索引 index

    文档存储的地方,类似于MySQL中的数据库。建立"索引"之后,可以直接往 索引 中写入"文档"

    字段 Field

    字段是ES中JSON数据的键,相当于Mysql数据表的字段

    映射 mapping

    映射是对文档中每个字段的类型进行定义

    mappings 映射相当于表结构

    每个文档都有映射,但是在大多数使用场景中,我们并不需要显示的创建映射,因为ES中实现了动态映射

    string类型由text和keyword类型替代

    • text 类型,需要分词则设置text类型,比如产品描述
    • keyword类型 ,不需要分词则设置keyword类型,比如email地址

    文档 document

     在MySQL中插入一行数据 和 ES中插入一个JSON文档是一个意思

    1. {
    2. "name":"",
    3. "age":18,
    4. "gender":1
    5. }

    一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是

    节点

    说明

    _index

    文档存储的地方

    _type

    文档代表的对象的类

    _id

    文档的唯一标识


    kibana客户端操作

    1.操作索引

    1. # 创建索引
    2. PUT person
    3. # 查询索引
    4. GET person
    5. # 删除索引
    6. DELETE person
    7. # 查询映射
    8. GET person/_mapping
    9. # 添加映射(创建索引库再添加映射)
    10. PUT person/_mapping
    11. {
    12. "properties":{
    13. "name":{
    14. "type":"keyword"
    15. },
    16. "age":{
    17. "type":"integer"
    18. }
    19. }
    20. }
    21. # ------------------------------------------------
    22. # 创建索引并添加映射
    23. PUT person
    24. {
    25. "mappings": {
    26. "properties": {
    27. "name":{
    28. "type": "keyword"
    29. },
    30. "age":{
    31. "type":"integer"
    32. }
    33. }
    34. }
    35. }
    36. # 索引库中添加字段
    37. PUT person/_mapping
    38. {
    39. "properties":{
    40. "address":{
    41. "analyzer": "ik_max_word",
    42. "type":"text"
    43. }
    44. }
    45. }

    2.操作文档

    1. # 创建索引并添加映射
    2. PUT person
    3. {
    4. "mappings": {
    5. "properties": {
    6. "name":{
    7. "type": "keyword"
    8. },
    9. "age":{
    10. "type":"integer"
    11. }
    12. }
    13. }
    14. }
    15. # 索引库中添加字段
    16. PUT person/_mapping
    17. {
    18. "properties":{
    19. "address":{
    20. "type":"text"
    21. }
    22. }
    23. }
    24. #------------文档操作----------------------
    25. # 查询索引
    26. GET person
    27. # 添加文档,指定id
    28. PUT person/_doc/1
    29. {
    30. "name":"太一",
    31. "age":20000,
    32. "address":"太阳星"
    33. }
    34. # 查询文档
    35. GET person/_doc/1
    36. # 添加文档,不指定id,自动生成id
    37. POST person/_doc/
    38. {
    39. "name":"帝俊",
    40. "age":20001,
    41. "address":"太阳星"
    42. }
    43. # 查询所有文档
    44. GET person/_search
    45. # 查询文档
    46. GET person/_doc/Rh8kOoIB_EsGPygii4_Y
    47. # 删除文档
    48. DELETE person/_doc/1
    49. # 修改文档 根据id修改 ,相当于把原来的删除,再把这个新添加进去。
    50. #即如果修改的时候只有一个属性,那么修改后也就只有一个属性
    51. PUT person/_doc/1
    52. {
    53. "name":"东皇太一",
    54. "age":20000,
    55. "address":"太阳星"
    56. }

    3.五花八门的查询(看我秀好吧

    3.1全文查询-match查询

    先执行GET person/_search,查询person索引库下所有文档,可得结果

    1. "hits" : [
    2. {
    3. "_index" : "person",
    4. "_type" : "_doc",
    5. "_id" : "Rh8kOoIB_EsGPygii4_Y",
    6. "_score" : 1.0,
    7. "_source" : {
    8. "name" : "帝俊",
    9. "age" : 20001,
    10. "address" : "太阳星"
    11. }
    12. },
    13. {
    14. "_index" : "person",
    15. "_type" : "_doc",
    16. "_id" : "1",
    17. "_score" : 1.0,
    18. "_source" : {
    19. "name" : "羲和",
    20. "age" : 20000,
    21. "address" : "太阴星"
    22. }
    23. }
    24. ]

    match查询

    会分析查询条件,先将查询条件进行分词,然后查询,求并集

    1. # match 先会对查询的字符串进行分词,在查询,求并集
    2. GET person/_search
    3. {
    4. "query": {
    5. "match": {
    6. "address": "太阳星"
    7. }
    8. }
    9. }

    查询的结果还是很意外的,太阳星和太阴星都查到了,因为会先分词查询,再取并集

    3.2 term查询-条件部分词

    词条查询不会分析查询条件(即查询条件不分词,归结为精确查找,只有当词条和查询字符串完全匹配时才匹配搜索

    1. GET person/_search
    2. {
    3. "query": {
    4. "term": {
    5. "address": {
    6. "value": "太阳星"
    7. }
    8. }
    9. }
    10. }

    遗憾的是,上面并未查找出来,出乎意料了吧

    根据address字段,建立倒排索引时,需要对其分词,产生多个词条,而词条集合中没有"太阳星"的词条,故而查询不到数据,

    如果你这么查,就不一样了,结果会把帝俊和太一查出来,也是意料之中

    1. GET person/_search
    2. {
    3. "query": {
    4. "term": {
    5. "address": {
    6. "value": "太阳"
    7. }
    8. }
    9. }
    10. }

    3.3 DSL查询

    索引库renzu中内容如下

    3.3.1 根据年龄查询

    1. #根据年龄查询
    2. GET renzu/_search
    3. {
    4. "query":{
    5. "match":{
    6. "age":20
    7. }
    8. }
    9. }

    3.3.2 查询年龄大于20岁的女性

    1. #bool查询表示多条件,must和filter都表示且的关系
    2. GET renzu/_search
    3. {
    4. "query":{
    5. "bool":{
    6. "filter":{
    7. "range":{
    8. "age":{
    9. "gt":20
    10. }
    11. }
    12. },
    13. "must":{
    14. "match":{
    15. "sex":"女"
    16. }
    17. }
    18. }
    19. }
    20. }

    3.3.3 一个字段匹配俩次找不同的值

    1. GET renzu/_search
    2. {
    3. "query":{
    4. "match":{
    5. "name": "张三 李四"
    6. }
    7. }
    8. }

    3.4 高亮显示

    1. # 搜索条件高亮显示
    2. GET renzu/_search
    3. {
    4. "query":{
    5. "match":{
    6. "name": "张三 李四"
    7. }
    8. },
    9. "highlight": {
    10. "fields": {
    11. "name": {}
    12. }
    13. }
    14. }

    结果是多一点标签一样的东西

    1. "highlight" : {
    2. "name" : [
    3. "<em>em><em>em>"
    4. ]
    5. }

    3.5聚合

    aggs:翻译为groupby,默认使用count

    1. #term 可以换为avg,max
    2. GET renzu/_search
    3. {
    4. "aggs": {
    5. "all_ages": {
    6. "terms": {
    7. "field": "age"
    8. }
    9. }
    10. }
    11. }

     "all_ages"名称是任意的。对应如下

    3.6指定响应字段

    1. #指定响应的字段
    2. GET renzu/_doc/1001?_source=id,name

    等价于

    1. #指定响应的字段
    2. GET renzu/_search
    3. {
    4. "query": {
    5. "match": {
    6. "id": "1001"
    7. }
    8. },
    9. "_source": ["id","name"]
    10. }

     3.7判断文档是否存在

    如果我们只需要判断文档是否存在,而不是查询文档内容,那么可以这样:

    HEAD  renzu/_doc/1001

    存在返回200 - OK

    不存在返回404 – Not Found

    3.8批量查询

    有些情况下可以通过批量操作以减少网络请求。如:批量查询、批量插入数据。

    1. #批量查询 等价于in()
    2. POST renzu/_doc/_mget
    3. {
    4. "ids" : [ "1001", "1003" ]
    5. }
    6. #1006 这条数据不存在,则found的值是false
    7. POST renzu/_doc/_mget
    8. {
    9. "ids" : [ "1001", "1006" ]
    10. }

    3.9_bulk操作

    在Elasticsearch中,支持批量的插入、修改、删除操作,都是通过_bulk的api完成的。

    批量插入数据:

    1. # 批量插入数据
    2. POST _bulk
    3. {"create":{"_index":"renzu","_id":2001}}
    4. {"id":2001,"name":"name1","age": 21,"sex": "男"}
    5. {"create":{"_index":"renzu","_id":2002}}
    6. {"id":2002,"name":"name2","age": 22,"sex": "男"}
    7. {"create":{"_index":"renzu","_id":2003}}
    8. {"id":2003,"name":"name3","age": 23,"sex": "女"}

    批量删除:

    由于delete没有请求体,所以,action的下一行直接就是下一个action。

    1. #批量删除
    2. POST _bulk
    3. {"delete":{"_index":"renzu","_id":2001}}
    4. {"delete":{"_index":"renzu","_id":2002}}
    5. {"delete":{"_index":"renzu","_id":2003}}

    3.10 分页

    Elasticsearch接受 from 和 size 参数:

    size: 结果数,默认10

    from: 跳过开始的结果数,默认0

    1. #跳过2个,显示2个
    2. GET renzu/_search?size=2&from=2

    也可以这么写

    1. #跳过2个,显示2个
    2. POST renzu/_search
    3. {
    4. "query" : {
    5. "match_all": {}
    6. },
    7. "from": 2,
    8. "size": 2
    9. }

    3.11 terms查询

    terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配。老师说了,都不会分词。。(我也没验证过对不对)

    1. #批量查询 等价于in()
    2. POST renzu/_doc/_mget
    3. {
    4. "ids" : [ "1001", "1003" ]
    5. }
    6. POST renzu/_search
    7. {
    8. "query" : {
    9. "terms" : {
    10. "id" : [1001,1003]
    11. }
    12. }
    13. }

    3.12 range查询

    range 过滤允许我们按照指定范围查找一批数据

    范围操作符包含:

    gt     大于
    gte大于等于
    lt小于
    lte小于等于
    1. #按照指定范围查找一批数据
    2. POST renzu/_search
    3. {
    4. "query": {
    5. "range": {
    6. "age": {
    7. "gte": 20,
    8. "lte": 30
    9. }
    10. }
    11. }
    12. }

    3.13 exits查询

    exists 查询可以用于查找文档中是否包含指定字段或没有某个字段

    1. # "exists": 是否包含指定字段
    2. POST renzu/_search
    3. {
    4. "query": {
    5. "exists": {
    6. "field": "email"
    7. }
    8. }
    9. }

    没有命中的结果如下:


    ElasticSearch集群

    1.集群与节点

    一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。集群默认名“elasticsearch”

    一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。

    一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中

    2.分片与复制 shards&replicas

    ElasticSearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。

    3.elasticsearch集群的搭建与测试

  • 相关阅读:
    性能测试 —— Jmeter定时器
    tf卡数据可以保存多久?如何恢复被格式化的tf卡数据
    VOIT Automotive EDI项目案例
    __declspec关键字:导入 导出
    基于SSM的个人博客系统(附论文+源码+课件)
    JS中获取元素属性的8大方法
    【备考网络工程师】如何备考2023年网络工程师之错题集篇(3)
    git分布式版本控制系统
    设计模式之(7)——装饰设计模式
    Java打印输出:8x8x
  • 原文地址:https://blog.csdn.net/m0_56799642/article/details/125997597