Elasticsearch笔记 (一)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: Elasticsearch笔记 (一)

一. 使用场景#


  • 全文检索-像淘宝京东类似的网上商城,当我们在在搜索框搜索某个商品名称时,网络没有问题的话,获取响应的速度,几乎和我们键盘起落的速度是一致的,这足以ES的魅力,亿万级别的搜索,秒秒钟完事
  • 一个正规的项目运行过程中,日志的产出是源源不断的,把日志的文本信息导入到ES,使用它的聚合功能轻松获取我们关系的内容,结合Kibana做图表分析,可视化日志记录,动态分析


二. 基本概念#


  • 2.1 什么是是全文检索
    全文检索就是计算机程序通过扫描文章中的每一个词,对必要的词建立一个索引(上篇博客我们使用ik分词器,帮助es分词),记录下这个词在文章中出现的位置和次数,这样当用户去查询的时候,他可以根据索引极快的查找出相应的内容


稍微解释下, 全文检索可以片面的理解成是从敲代码的人的角度上说的,假如你是用户,你会关心什么全文检索? 用户关系的是搜索结果!那好,对我们敲代码的来说,就是1.拿到用户搜索框输入的关键字送进ES (数据在存进es的时候,es对他们进行了索引)2.ES的程序会对关键字进行分词,拿着这些碎片去ES中的索引库里面的type中的field中匹配比对,那,那么多field,它和谁比对呢? 和标记上text属性的字段比对)

另外要了解的内容1.全文检索只处理文本不处理语义,2.全文检索忽略英文的大小写 3.结果可能不止一个,并且有相关得分


  • 2.2 与关系型数据库名称上的对比


mysql Elasticsearch
Database 数据库 indices 索引
Table 数据表 type 类型
Row 行 document 文档
Columns 列 Field 字段


其实大多数人都是先接触的关系型数据库,我也是,可能一开始感觉着好别扭,但是再回头来看,好像他的名字比传统的关系型数据库名什么行啊列啊,更合理一些


  • 2.3 分片(shard)和副本(replica)


通过图片可以看到: 数据分成三部分,分别存放在三个分片里面,而且每个分片都有自己的副本,这样就算是一台es,它同样是分布式


三. 怎么玩?#



这部分纯属扯皮了,不说语法,说一下我对它的感觉,首先呢, 为什么学它? 图方便快速呗,大部分情况下,是需要使用它的全文检索功能,但是总得有个下手点吧,不用说一开始都是环境配置一顿整,访问个9200看到版本号,也算是开个头了,然后呢? 先不用想他怎么检索,怎么花里胡哨的检索,我们得知道自己想检索什么!先把数据给它,思路就来了,先去搞数据,下一步自然就是创建新的索引(数据库),循环把我们的数据送进es的索引里面.到这里,也算是完成一半的任务了,下面就是使用人家提供好的api去索引库,检索就好了. 先有个大概的思路.想干什么,怎么干,往下学


四. 原生语法#



  • elasticsearch采用的REST风格的api,也就是说,其实他就是一次http的请求

下面会有一些关键字 也就是json的 key部分,对我们来说,一般可以见名知意


4.1.1 创建索引库#


  • 请求方式: PUT
  • 请求路径: /索引库名
  • 请求参数: json


PUT /xiaowu1
{
  "settings": {
    "number_of_shards": 1
    , "number_of_replicas": 1
  }
}


成功的相应:


{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "xiaowu1"
}


4.1.2 查看数据库#


  • 请求方式: GET
  • 格式: GET /索引库名


GET /xiaowu1


响应:相关的源信息


{
  "xiaowu1": {
    "aliases": {},
    "mappings": {},
    "settings": {
      "index": {
        "creation_date": "1552653562807",
        "number_of_shards": "1",
        "number_of_replicas": "1",
        "uuid": "u0tMDD-pQXaHb77cTPorZA",
        "version": {
          "created": "6020499"
        },
        "provided_name": "xiaowu1"
      }
    }
  }
}


4.1.3 删除索引库#


  • 请求方式: DELETE
  • 格式: DELETE /索引库名


4.2.1 配置映射#


在玩搜索之前我们要思考如何定义文档的,如文档包括哪些字段,这些字段是否保存,是否索引,是否分词等等, 实际上就像是在描述我们数据库中的一张表,有哪些列,列是什么类型的,是主键不?自增长不?


以后看到"mappings":{} 就像查看关系型数据库中对整张表的定义一样

  • 请求方式: PUT
  • 格式: PUT /索引库名/_mapping/类型名
PUT /xiaowu/_mapping/goods
{
  "properties": {      ---属性关键字
    "name":{           ---name为字段名,可以不止一个,就像数据库中的列,你开心,多少个都行
      "type": "text",  ---类型常用:integer,long,text,object,date,short,string,float 
      "index": true,   ---是否索引  默认true
      "store": false,   ---是否存储  默认false
      "analyzer": "ik_max_word" ---是否分词
    },
     "images": {
      "type": "keyword",  
      "index": "false"
    },
    "age": {
      "type": "float"
    }
  }
}


1 .字符串类型有两种

  • text : 可检索
  • keyword : 不可检索


2 .数值类型

  • 基本数值类型: long ,float,byte,double...
  • 浮点数高精度类型: scaled_float
  • 它需要我们指定一个精度因子,比如10,100,es把真实值乘以这个精度因子存储,取出后还原,(商品价格)


  1. 日期类型:
  • Date


  1. 存储对象

{girl:{name:"张三",age:23}


而是会把它处理成 girl.namegirl.age


5 .store

  • 表示,是否将数据额外存储,意思是,如果不存储,用户就搜索不出来
  • 在solr中如果为store设为false,那么用户就搜索不出来这个字段
  • 但是elasticsearch中,并不用store的值控制是否可以被搜索出来,即便他是false,用户仍然可以搜索出结果,原因是elasticsearch的底层,在创建文档时,会将文档的原始数据备份保存到一个叫 _source的属性中,而我们可以通过过滤_source选择那些需要显示,那些不需要显示,这样如我们把store的值设置为ture它就会多储存一份,得不偿失(store相当于作废了)


4.2.2 向已经存在的索引库中添加数据(不一定要指定ID)#


  • 请求方式: POST
  • 格式: POST /索引库名/类型名{}


POST /changwu/item/
{
    "title":"小米手机",
    "price":2699.00
}


响应:


{
  "_index": "changwu",
  "_type": "item",
  "_id": "Pj6bgWkB3eQnUSvRfoa2",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 5,
  "_primary_term": 6
}


id,是自动生成的当前数据的标识,我们还可以指定


POST /changwu/item/2


4.2.3 基本查询#

  • 请求方式: GET
GET /索引库名/_search
{
  "query": {
    "查询类型":{
      "查询条件": "条件值"
    }
  }
}


  • query是Elasticsearch内置的一个对象,里面有不同的查询属性

使用,SpringDataElasticsearch玩复杂查询的时候,免不了会BuildQueryXXX

  • 查询类型:
  • match_all 查询所有
  • match
  • term
  • range
  • 查询条件根据类型的不同而不同,(就像关系型数据库中表的字段不同...)


4.2.4 匹配查询 match#


or 关系


match类型查询,会把查询条件进行分词,然后再查询,词条之间是or关系,按照相关性得分排序


GET /goods/_search
{
  "query": {
    "match":{
      "price": 269900
    }
  }
}


and关系


很多情况下我们希望更精确的查找,于是我们使用 and关系


GET /xiaowu/_search
{
     "query":{
       "match":{
         "title":{
            "query":"米手机",
            "operator":"and"
         }
       }
     }
}


这样他在分词的时候,米--手机同时都匹配上才会显示出结果!


假设有这样一种情况,用户给定的条件分词后,有五个词,但是其中的四个是在描述他想要搜索的内容,如果使用or,毫无疑问,一大堆杂七杂八的东西被查询出来,如果使用and,es很可能把那个目标文档排除,那该怎么办呢?看下面!


  • match支持使用minimum_should_match 最小匹配参数,通常设置为一个百分数


GET /xiaowu/_search
{
     "query":{
       "match":{
         "title":{
            "query":"米手机",
            "minimum_should_match":"75%"
         }
       }
     }
}


意思是,用户输入的词条满足75%的匹配程,我就认为是匹配上了, ---用户输入的检索条件,被分解为三个词,3*0.75=2.25 也就是说,这三个词,至少有两个是匹配上的,es就认为匹配成功

4.2.5多字段查询 muti_match#


  • muti_match和match一样,但是不同的是它可以同时在多个字段中检索


GET /xiaowu/_search
{
     "query":{
       "multi_match":{
            "query":"米",
            "fields":["title"]
       }
     }
}


他的fields接受一个字段数组


4.2.6 词条查询(term)#

  • 和前面的查询条件不同的是term,它被用作精确查询,比如数字,时间,布尔,和字段属性为keyword类型的关键字


GET /xiaowu/_search
{
   "query": {
     "term": {
       "price": {
         "value": "1888"
       }
     }
   }
}



4.2.7 多词条精确匹配#


  • 和term一样的精确匹配,但是不同的是它支持同时使用多个词条进行精确匹配,如果只要索引库中的文档包含指定值中的任意一个,都算作满足条件


4.3.1 结果过滤#


 默认情况下,elasicsearch在搜索的结果在,会把文档保存在_source里面的所有字段都返回,如果我们想获取里面的部分结果,添加_soure过滤


GET /xiaowu/_search
{
  "_source": ["过滤字段"], 
   "query": {
     "term": {
       "price": {
         "value": "1888"
       }
     }
   }
}


  • 另外,_source里面还有两个属性
  • "includes":[想显示的字段]
  • "excludes":[不想显示的字段]


解读查询结果:


{
  "took": 1,    ----花费时长,单位毫秒
  "timed_out": false,  ----是否超时
  "_shards": {      --- 分片信息
    "total": 1,    
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {     --- 命中的结果
    "total": 1, --- 结果总数
    "max_score": 4.765019, ---相关性的最高得分
    "hits": [      --- 搜索结果的对象数组
      {
        "_index": "goods",   ---  索引
        "_type": "docs",     --- 类型
        "_id": "180",        ---  唯一id
        "_score": 4.765019,  ---文档得分
        "_source": {            --- 文档的数据源,(前面说过,结果都在_source里面)
          "id": 180,
          ...
          }


  • 在所有的index里面查询指定的字段


GET _search
{
  "query": {
   "match": {
     "title": "小米2手机"
   }
  }
}


4.4.1 智能判断#


  • 新增属性的时候,可以添加新的字段


POST /xiaowu/goods/
{
  "title":"es666",
  "hehe":true
}


查询结果:


{
        "_index": "xiaowu",
        "_type": "goods",
        "_id": "Qz69gWkB3eQnUSvRC4ah",
        "_score": 1,
        "_source": {
          "title": "es666",
          "hehe": true
        }


查看映射


{
  "xiaowu": {
    "mappings": {
      "goods": {
        "properties": {
          "age": {
            "type": "float"
          },
          "hehe": {
            "type": "boolean"
          },
          "images": {
            "type": "keyword",
            "index": false
          },
          "name": {
            "type": "text",
            "store": true,
            "analyzer": "ik_max_word"
          },
          "price": {
            "type": "float"
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}


这样看,其实我们在上面配置的映射关系就没有必要了,Elasticsearch会智能化的推断出字段的type,比如true它推断为boolean, 但是有问题的是title 它推断为 text ,title.keyword是 keyword类型


4.5.1 修改数据(指明ID)#

把上面的POST转变成PUT就是修改

  • id对应的文档存在则修改
  • id对应的文档不存在则新增


4.6.1 删除数据#


语法: DELETE /索引库名/类型名/id


4.7.1 高级玩法-布尔组合#


看得懂,会使用Elasticsearch的高级玩法很重要,这关系着,能不能理解如何使用它的原生api进行高级查询


  • 布尔组合,结合了其他的查询,实现了这样的功能, -- 我的搜索结果中,一定含有谁(must),一定不含有谁(must_not),可能含有谁(should)


GET /xiaowu/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "米"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "title": "大"
          }
        }
      ],
     "should": [
       {
         "match": {
           "price": "999"
         }
       }
     ]
    }
  }
}


4.7.2 高级玩法--范围查询range#


  • range实现的是查询出满足某个区间的结果


GET /xiaowu/_search
{
  "query": {
    "range": {
      "FIELD": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}


关键字 含义
gte 大于等于
lte 小于等于
gt 大于
lt 小于


4.7.3 模糊查询---fuzzy#


模糊查询很人性化,它允许用户在编辑的条件有拼写错误,但是出现偏差的编辑差距不得超过2


GET /xiaowu/_search
{
  "query": {
    "fuzzy": {
      "title": {
       "value": "appla",
       "fuzziness": 1
       }
    }
  }
}


  • 这样查询是可以查询出apple的
  • "fuzziness": 限定编辑距离


4.7.4 过滤---filter#


  • 1.有条件查询进行过滤


查询就会影响文档的相关性得分,假如我们只是想在现有的查询基础上,根据需求过滤下一些结果,却不想影响文档的相关性得分的话filter就派上用场了


GET /changwu/_search
{
    "query":{
        "bool":{
          "must":{ "match": { "title": "小米手机" }},
          "filter":{
                "range":{"price":{"gt":2000.00,"lt":3800.00}}
          }
        }
    }
}


filter中还可以在bool组合过滤


  • 2.无条件查询进行过滤


如果一次查询只有过滤,没有查询条件,不希望进行评分,我们可以使用constant_score

GET /changwu/_search
{
    "query":{
        "constant_score":   {
            "filter": {
               "range":{"price":{"gt":2000.00,"lt":3000.00}}
            }
        }
}


4.7.5 --- 排序 sort#


排序sort和query是有先后顺序的,先query,再排序


  • 单字段排序


GET /changwu/_search
{
  "query": {
    "match": {
      "title": "手机"
    }
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}


  • 多字段排序


看上面的sort后面的条件,是个数组,因此我们可以写条件,按多个字段进行排序


聚合:aggregations#


  • 基本概念,两个新概念,在Elasticsearch中的聚合分为两个部分,聚合为桶bucket度量
  • 桶就像mysql中的分组查询,比如说学号相同,姓名相同的肯定是同一个人,我们就把它当成一组,在这里就是一个桶
  • 度量--以每个桶为基础,做运算

当然Elasticsearah里面分桶的方式很多

  • Terms Aggregation:根据词条内容分组,词条内容完全匹配的为一组
  • Range Aggregation:数值和日期的范围分组,指定开始和结束,然后按段分组,这个范围要手动告诉他,0-10 10-15 15-30等
  • Histogram Aggregation:根据数值阶梯(柱状图)分组,与日期类似, 告诉他一个段就行了,她会自动的分组
  • Date Histogram Aggregation:根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组

常用的度量方法:

  • Avg Aggregation:求平均值
  • Max Aggregation:求最大值
  • Min Aggregation:求最小值
  • Percentiles Aggregation:求百分比
  • Stats Aggregation:同时返回avg、max、min、sum、count等
  • Sum Aggregation:求和
  • Top hits Aggregation:求前几
  • Value Count Aggregation:求总数


es中进行过滤,排序,聚合的字段,不能被分词!!!!*


GET /cars/_search
{
  "size": 0,
  "aggs": {
    "popular_brand": {
      "terms": {
        "field": "color"
      },
      "aggs": {
        "priceAvg": {
          "avg": {
              "field": "price"
          }
        }
      }
    }
  }
}


一般都是先聚为桶,然后在桶的基础上进行度量



相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
7月前
|
安全
【Elasticsearch6】安装笔记
【Elasticsearch6】安装笔记
47 2
|
8月前
|
关系型数据库 MySQL 索引
|
8月前
|
前端开发 Java iOS开发
elasticsearch8.1源码编译笔记
elasticsearch8.1源码编译笔记
149 0
|
8月前
|
自然语言处理 安全 关系型数据库
|
JSON 安全 搜索推荐
白日梦的Elasticsearch实战笔记,32个查询案例、15个聚合案例、7个查询优化技巧(一)
白日梦的Elasticsearch实战笔记,32个查询案例、15个聚合案例、7个查询优化技巧(一)
1095 0
|
Java 数据库 Docker
Elasticsearch笔记
Elasticsearch笔记
162 0
Elasticsearch笔记
|
存储 Web App开发 搜索推荐
Elasticsearch笔记(集群插件、kibana、什么是倒排索引)
Elasticsearch笔记(集群插件、kibana、什么是倒排索引)
Elasticsearch笔记(集群插件、kibana、什么是倒排索引)
Elasticsearch核心技术与实战-极客课程笔记
Elasticsearch核心技术与实战-极客课程笔记
481 0
Elasticsearch核心技术与实战-极客课程笔记
|
搜索推荐
ElasticSearch笔记
ElasticSearch笔记
144 0
ElasticSearch笔记
|
SQL 缓存 自然语言处理
白日梦的Elasticsearch实战笔记,32个查询案例、15个聚合案例、7个查询优化技巧(二)
白日梦的Elasticsearch实战笔记,32个查询案例、15个聚合案例、7个查询优化技巧(二)
992 1