ES进阶实战

索引的一些操作

  • 集群健康状态:/_cluster/health

  • 创建索引

  • 查看索引

  • 删除索引

索引的mapping映射

index

The index option controls whether field values are indexed. It accepts true or false and defaults to true. Fields that are not indexed are typically not queryable.

  • 创建索引的同时创建mappings

  • 查看分词效果

  • 尝试修改

  • 为已存在的索引创建mappings

{
    "properties":{
        "id": {
            "type":"long"
        },
        "age":{
            "type":"integer"
        },
        "nickname":{
            "type":"keyword"
        },
        "money1": {
            "type": "float"
        },
        "money2":{
            "type": "double"
        }, 
        "sex":{
            "type": "byte"
        }, 
        "score": {
            "type": "short"
        },
        "is_teenager":{
            "type":"boolean"
        },
        "birthday":{
            "type":"date"
        },
        "relationship":{
            "type":"object"
        }
    }
}

∶某个属性一旦被建立,就不能修改了,但是可以新增额外属性

主要数据类型

  • text, keyword, string
  • long, integer, short, byte
  • double, float
  • boolean
  • date
  • object
  • 数组不能混,类型一致

字符串

  • text∶文字类需要被分词被倒排索引的内容,比如 商品名称、商品详情, 商品介绍,使用text。
  • keyword∶不会被分词,不会被倒排索引,直接匹配搜索,比如 订单状态, 用户qq, 微信号, 手机号 等,这些精确匹配,无需分词。

文档的基本操作

添加文档数据

POST /my_doc/_doc/1->{索引名}/_doc/{索引ID}(是指索引在es中的id,而不是这条记录的id,比如记录的id从数据库来是1001,并不是这个。如果不写,则自动生成一个字符串。建议和数据id保持一致>)

{
    "id": 1001, 
    "name": " imoOC-1",
    "desc":"imooc is very good,慕课网非常牛!",
    "create_date":"2019-12-24"
}
{
    "id": 1002, 
    "name": "imooC-2",
    "desc":"imooC is fashion,慕课网非常时尚!",
    "create_date":"2019-12-25"
}
{
    "id": 1003, 
    "name":"imooC-3",
    "desc":"imooc is niubility,慕课网很好很强大!",
    "create_date":"2019-12-26"
}
{
    "id":1004,
    "name":"imooC-4",
    "desc":"imooc is good~! ", 
    "create_date":"2019-12-27"
}
{
    "id": 1005, 
    "name":"imooc-5",
    "desc":"慕课网 is 强大!",
    "create_date":"2019-12-28"
}
{
    "id": 1006,
    "name":"imooc-6",
    "desc":"慕课是一个强大网站!",
    "create_date":"2019-12-29"
}
{
    "id": 1007,
    "name":"imooc-7",
    "desc":"慕课网是很牛网站!",
    "create_date":"2019-12-30"
}
{
    "id'": 1008, 
    "name":"imoOC-8",
    "desc":"慕课网是很牛网站!",
    "create_date":"2019-12-31"
}
{
    "id": 1009,
    "name":"imooC-9",
    "desc":"在慕课网学习很久!",
    "create_date":"2020-01-01"
}
  • 注∶如果索引没有手动建立mappings,那么当插入文档数据的时候,会根据文档类型自动设置属性类型。这个就是es的动态映射,帮我们在index索引库中去建立数据结构的相关配置信息。
  • "fields":{"type":"keyword"},对一个字段设置多种索引模式,使用text类型做全文检索,也可使用keyword类型做聚合和排序
  • "ignore above":256 设置字段索引和存储的长度最大值,超过则被忽略

删除和修改

  1. 删除文档 DELETE /my_doc/_doc/1
    • 注:文档删除不是立即删除,文档还是保存在磁盘上,索引增长越来越多,才会把那些曾经标识过删除的,进行清理,从磁盘上移出去。
  2. 修改文档
    • 局部
    POST /my_doc/_doc/1/_update
    {
       "doc": {
           "name":"慕课"
        }
    }   
    
    • 全量替换
    PUT /my_doc/_doc/1
    {
       "doc": {
           "id":1001
           "name":"immoc-01"
           "desc":"imooc is very good!"
           "create_date":"2022-05-19"
        }
    }   
    
    • 注:每次修改后,version会更改

查询

查询文档
常规查询

GET /index_demo/_doc/1 
GET /index_demo/_doc/_search

查询结果

{
  "_index":"my_doc", 
  "_type": "_doc", 
  "_id": "2", 
  "_score":1.0, 
  "_version":9, 
  "_source":{
      "id": 1002, 
      "name":"imooc-2",
      "desc":"imooc is fashion", 
      "create_date":"2022-05-19"
  }
}

元数据

  • index∶文档数据所属那个索引,理解为数据库的某张表即可。
  • _type∶文档数据属于哪个类型,新版本使用_doc 。
  • _id∶文档数据的唯一标识,类似数据库中某张表的主键。可以自动生成或者手动指定。
  • score∶查询相关度,是否契合用户匹配,分数越高用户的搜索体验越高。
  • _version∶版本号。
  • _source∶文档数据,json格式。

定制结果集

GET /index_demo/_doc/1?_source=id,name 
GET /index_demo/_doc/_search?_source=id,name

判断文档是否存在

HEAD /index_demo/_doc/1

文档乐观锁控制if_seq_noif_primary_term

观察操作

  • 插入新数据
    PUT /my_doc/_doc   
    
    {
        "id": 1010, 
         "name": " imooc-1010",
         "desc":"imoocimmoc",
         "create_date":"2022-05-19"
    }
    
    # 此时 _version 为1
    
  • 修改数据
    POST /my_doc/_doc/{_id}/_update
    
    {
         "name": " imooc-慕课"
    }
    
    # 此时 _version 为2
    
  • 模拟两个客户端操作同一个文档数据,version都携带为一样的数值
     # 操作1 
     POST  /my_doc/_doc/{_id}/_update?if_seq_no={数值}&if_primary_term={数值}
     {
       "doc": {
         "name"∶"慕课1"
       }
     }
    
     # 操作2
     POST/my_doc/_doc/{_id}/_update?if_seq_no={数值}&if_primary_term={数值}
     {
       "doc": {
         "name"∶"慕课2"
       }
     }
    

版本元数据

分词与内置分词器

什么是分词?
把文本转换为一个个的单词,分词称之为analysis。es默认只对英文语句做分词,中文不支持,每个中文字都会被拆分为独立的个体。

  • 英文分词∶I study in imooc.com
  • 中文分词∶我在慕课网学习
POST /_analyze
{
    "analyzer": "standard", 
    "text"∶"text文本"
}
POST /my_doc/_analyze
{
    "analyzer":"standard", 
    "fieLd":"name", 
    "text"∶"text文本"
}

es内置分词器

  • standard∶默认分词,单词会被拆分,大小会转换为小写。
  • simple∶按照非字母分词。大写转为小写。
  • whitespace∶按照空格分词。忽略大小写。
  • stop∶去除无意义单词,比如 the/a/an/is ….
  • keyword∶不做分词。把整个文本作为一个单独的关键词。

建立IK中文分词器

ik中文分词器:https://download.csdn.net/download/weixin_44393822/85414235?spm=1001.2014.3001.5503
测试中文分词器效果:

POST /_analyze
{
    "analyzer": "ik_max_word", 
    "text"∶"上下车流量很大"
}

自定义中文词库

  1. {es}/plugins/ik/config 下,创建 vim custom.dic
  2. 并且添加内容
慕课网
骚年
  1. 配置自定义扩展词典 <entry key="ext_dict">custom.dic</entry>
  2. 重启

DSL搜索

入门语法

请求参数的查询(QueryString)
查询【字段】包含【内容】的文档

GET   /shop/_doc/_search?q=desc∶慕课网
GET   /shop/_doc/search?q=nickname:慕&q=age:25

text与keyword搜索对比测试(keyword不会被倒排索引,不会被分词)

GET   /shop/_doc/_search?q=nickname:super
GET   /shop/_doc/_search?q=username:super
GET   /shop/_doc/_search?q=username:super hero

这种方式称之为QueryString查询方式,参数都是放在url中作为请求参数的。

DSL基本语法
QueryString用的很少,一旦参数复杂就难以构建,所以大多查询都会使用DSL来进行查询更好。

  • Domain Specific Language
  • 特定领域语言
  • 基于JSON格式的数据查询
  • 查询更灵活,有利于复杂查询

DSL格式语法∶

# 查询
POST   /shop/_doc/_search
{
    "query":{
        "match": {
          "deSc"∶"慕课网"
         }
     }
}

# 判断某个字段是否存在
{
    "query": {
        "exists":{
            "field":"desc"
        }
    } 
}
  • 语法格式为一个json object,内容都是key-value键值对,json可以嵌套。
  • key可以是一些es的关键字,也可以是某个field字段,后面会遇到

搜索不合法问题定位
DSL查询的时候经常会出现一些错误查询,出现这样的问题大多都是json无法被es解析,他会像java那样报一个异常信息,根据异常信息去推断问题所在,比如json格式不对,关键词不存在未注册等等,甚至有时候不能定位问题直接复制错误信息到百度一搜就能定位问题了。

查询所有与分页

match_all
在索引中查询所有的文档GET /shop/_doc/_search

POST     /shop/_doc/_search
{
    "query":{
        "match_all":{}
     },
     "_source":["id","nickname","age"]
}
  • Head可视化操作

分页查询
默认查询是只有10条记录

POST    /shop/_doc/_search
{
    "query":{
        "match_all":{}
     },
    "form": 0,
    "size": 10
}


{
    "query":{
        "match_all":{}
     },
     "_source":["id","nickname","age"],
    "form": 5,
    "size": 5
}

  • Head可视化操作

DSL搜索 - term/match

term精确搜索与match分词搜索
搜索的时候会把用户搜索内容,比如"慕课网强大"作为一整个关键词去搜索,而不会对其进行分词后再搜索

POST    /shop/_doc/_search
{
    "query":{
       "term": {
        "desc"∶"慕课网"
        }
    }
}
对比:
{
    "querry":{
        "match":{
           "desc∶"慕课网"
        }
    }
}
  • 注∶match会对 慕课网 先进行分词(其实就是全文检索),在查询,而term则不会,直接把 慕课网 作为一个整的词汇去搜索。
  • head可视化操作对比

terms多个词语匹配检索
相当于是tag标签查询,比如慕课网的一些课程会打上 前端/后端/大数据/就业课 这样的标签,可以完全匹配做类似标签的查询

POST     /shop/_doc/_search
{
    "query":{
        "terms": {
            "desc":["慕课网","学习","骚年"]
          }
     }
}

match_phrase短语匹配

match∶分词后只要有匹配就返回,match_phrase∶分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。(搜索比较严格)

  • slop∶允许词语间跳过的数量
POST    /shop/_doc/_search
{
    "query": {
        "match_phrase": {
            "desc": {
                "query"∶"大学 毕业 研究生",
                "slop": 2
            }
        }
    }
} 

DSL搜索 - match(operator) / ids

match扩展

  • operator
    • or∶搜索内容分词后,只要存在一个词语匹配就展示结果
    • and∶搜索内容分词后,都要满足词语匹配
    POST    /shop/_doc/_search
    {
       "query":{
           "match":{
             "desc"∶"慕课网"”
            }
         }
    }
    #等同于
    {
        "query":{
            "match":{
                "desc":{
                    "query"∶"xbox游戏机",
                    "operator": "or"
               }
            }
        }
    }
     # 相当于 select * from shop where desc='xbox' or|and desc='游戏机'
    
  • minimum_should_match∶最低匹配精度,至少有【分词后的词语个数】x百分百,得出一个数据值取整。举个例子∶ 当前属性设置为 70,若一个用户查询检索内容分词后有10个词语,那么匹配度按照10x70%=7,则desc中至少需要有7个词语匹配,就展示;若分词后有8个,则8x70%=5.6,则desc中至少需要有5个词语匹配,就展示。
  • minimum_should_match也能设置具体的数字,表示个数
POST    /shop/_doc/_search
{
    "query":{
        "match":{
            "desc":{
                "query"∶"女友生日送我好玩的xbox游戏机",
                "minimum_shouLd_match":"60%"
             }
         }
     }
}

根据文档主键ids搜索
GET /shop/_doc/1001
查询多个

POST    /shop/_doc/_search
{
    "query":{
        "ids'":{
            "type": "_doc",
            "values":["1001","1010","1008"]
         }
     }
}

总结

  1. 本阶段主要针对es的讲解,首先我们讲了什么是分布式搜索,以及lucene、solr与es的对比,他们都是全文检索,而且底层基于lucene,目前已es使用最为流行;随后我们又讲了什么是倒排索引,这是搜索引擎里的核心。此外呢我们也在最一开始就讲了集群原理,因为es的使用主要以集群为主,此外还包含了主分片与副本分片的概念。
  2. 学习es必须要安装,首先我们在linux中安装了es7,另外呢,我们也安装了head插件,这个插件是基于es的可视化操作,使用起来非常方便,当然我们也通过使用postman对es做了一些基本的操作。
  3. 接下来我们对es做了一个快速入门,主要是创建索引与映射,文档的CRUD以及es乐观锁的讲解。
  4. 在es中,默认的分词是基于英文的,毕竟是老外发明的,对中文支持的不好,所以我们需要自己去安装中文分词器,如此就能对中文词语做分词了,安装好之后,还能对特定的词汇去设置自定义词库,比如 慕课网 不是词语,我们就能为他自定义。
  5. DSL搜索是es中的复杂查询,而且也是使用的最多的,其中主要包含了term/match/multi_match/boost/bool/sort/highlight 等,这些搜索可以满足日常使用,如果语法忘记,百度上搜一下即可,json没必要手写,直接复制修改就能达到效果。另外我们也讲了分页,分页的话有一点需要注意,那就是深
    度分页,分页太深,会造成性能的影响。此外我们还讲了滚动搜索,这个相当于是快照分页功能,可以大批量的把数据查询出来。
  6. 批量操作在redis中我们也提到过,在es中也有,因为批量操作可以提高性能与吞吐量,查询使用mget,增加删除修改使用bulk就能达到效果。
  7. es集群是非常重要的,在企业里es往往以集群的形式存在,一般以3个节点居多,在老版本中,es集群有一个需要注意的就是脑裂问题,一定要设置半数master节点以上的投票,才能选举成为一个master,否则会出现脑裂现象,这个在老版本es中需要注意。
  8. es提供了rest-api,所以我们可以使用es结合springboot来实现检索功能,主要是通过elasticsearchTemplate来进行相关检索,比如创建索引,文档的crud,分页,高亮,排序等。
  9. 要查询商品数据,那么我们必须要把数据同步到es中,这里我们使用了logstash,需要注意,版本要和es的安装版本一致,同步好以后就能检索相关数据了。自动同步以后,logstash会使用自定义的模板为我们创建mappings映射,这样的话中文分词就不行了,我们可以手动创建或者使用自定义logstash模板来设置field的中文分词就行了。
    10.最后我们把es整合到了项目中,实现了基于商品的全文检索并且还有分页高亮以及排序。
posted @ 2023-02-20 17:29  程序员波特  阅读(53)  评论(0)    收藏  举报