ElasticSearch的基本用法

文章介绍了Elasticsearch作为开源分布式搜索引擎的角色,以及它如何用于搜索、日志分析和系统监控。重点讲述了正向索引与倒排索引的概念,强调倒排索引在提升搜索效率中的作用。此外,还讨论了Elasticsearch中的mapping映射,用于定义字段数据类型和搜索特性,并展示了如何进行索引库的CRUD操作,包括创建、查询、修改和删除。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.elasticsearch的认识与介绍

什么是elasticsearch?
  • 一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能
什么是elastic stack(ELK)?
  • 是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch被广泛应用在日志数据分析、实时监控等领域。
什么是Lucene?
  • 是Apache的开源搜索引擎类库,提供了搜索引擎的核心API

正向索引

例如给下表(tb_goods)中的id创建索引:
image.png
基于title做模糊查询,只能是逐行扫描数据,流程如下:
1)用户搜索数据,条件是title符合"%手机%"
2)逐行获取数据,比如id为1的数据
3)判断数据中的title是否符合用户搜索条件
4)如果符合则放入结果集,不符合则丢弃。
5)查出所有结果并返回
这时只能是全表扫描,随着数据量增加,其查询效率也会越来越低。当数据量达到数百万时,就是一场灾难。

倒排索引

倒排索引中有两个非常重要的概念

  • 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息
  • 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:“我”、“是”、“中国人”、“中国”、"国人"这样的几个词条。

创建倒排索引是对正向索引的一种特殊处理,流程如下

  • 将每一个文档的数据利用算法分词,得到一个个词条
  • 创建表,每行数据包括词条、词条所在文档id、位置等信息
  • 因为词条唯一性,可以给词条创建索引,例如hash表结构索引

image.png
倒排索引的搜索流程如下(以搜索"华为手机"为例):
1)用户输入条件"华为手机"进行搜索。
2)对用户输入内容分词,得到词条:华为手机
3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1 2 3
4)拿着文档id到正向索引中查找具体文档。
image.png
elasticsearch中有很多独有的概念,与mysql中略有差别,但也有相似之处。
我们统一的把mysql与elasticsearch的概念做一下对比:
image.png

  • Mysql:擅长事务类型操作,可以确保数据的安全和一致性
  • Elasticsearch:擅长海量数据的搜索、分析、计算

elasticsearch和kibana以及ik分词器的安装请参考:elasticsearch的安装

2.索引库操作

索引库就类似数据库表,mapping映射就类似表的结构。我们要向es中存储数据,必须先创建“库”和“表”。就需要编写DDL语句实现创建库和表。之前我们对比理解过 mapping等同于数据库中DDL。

2.1.mapping映射属性

mapping是对索引库中文档的约束,具体的映射针对的是字段。常见的mapping属性包括:

  • type:字段数据类型,常见的简单类型有:
    • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
    • 数值:long、integer、short、byte、double、float、
    • 布尔:boolean
    • 日期:date
    • 对象:object
    • geo_point gps坐标
  • index:是否创建索引,默认为true
  • analyzer:使用哪种分词器(前提是:要分词 才需要指定分词器)
  • properties:该字段的子字段

对于下面的json文档(理解成数据库中的行):

{
  "age": 28,
  "weight": 59.1,
  "isMarried": false,
  "info": "腾讯公司大老板",
  "email": "123456@qq.com",
  "score": [99.1, 99.5, 98.9],
  "name": {
    "firstName": "云腾",
    "lastName": "马"
  }
}

对应的每个字段映射(mapping):

  • age:类型为 integer;参与搜索,因此需要index为true;无需分词器
  • weight:类型为float;参与搜索,因此需要index为true;无需分词器
  • isMarried:类型为boolean;参与搜索,因此需要index为true;无需分词器
  • info:类型为字符串,需要分词,因此是text;参与搜索,因此需要index为true;分词器可以用ik_smart
  • email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,因此需要index为false;无需分词器
  • score:虽然是数组,但是我们只看元素的类型,类型为float;参与搜索,因此需要index为true;无需分词器
  • name:类型为object,需要定义多个子属性
    • name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器
    • name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器

2.2.索引库的CRUD

这里我们统一使用Kibana编写DSL的方式来演示。

2.2.1.创建索引库和映射【练习】

基本语法:
  • 请求方式:PUT
  • 请求路径:/索引库名,可以自定义
  • 请求参数:mapping映射

格式:

PUT /索引库名称
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

示例:

PUT /user_info
{
  "mappings": {
    "properties": {
      "age" :{
        "type": "integer"
      },
      "weight":{
        "type": "double"
      },
      "isMarried":{
        "type": "boolean"
      },
      "info":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email":{
        "type": "keyword",
        "index": false
      },
      "score":{
        "type": "float"
      },
      "name":{
          "properties": {
            "firstName":{
              "type":"keyword"
            },
            "lastName":{
              "type":"keyword"
            }
          }
      }
    }
  }
}

2.2.2.查询索引库

基本语法

  • 请求方式:GET
  • 请求路径:/索引库名
  • 请求参数:无

格式

GET /索引名

GET /user_info
image.png

2.2.3.修改索引库

倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping
虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。
语法说明

PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "text"
    }
  }
}

2.2.4.删除索引库

语法:

  • 请求方式:DELETE
  • 请求路径:/索引库名
  • 请求参数:无

格式:

DELETE /索引名称

3.文档操作

3.1.新增文档

语法:

POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}

示例:

POST /user_info/_doc/1
{
  "info": "这是测试信息",
  "email": "zy111@163.cn",
  "name": {
    "firstName": "云",
    "lastName": "赵"
  }
}

响应:

注意,文档都会有一个唯一标识,我们把它叫做_id (文档ID) 类似于数据库的一行都会有一个主键来作为唯一标识一样。

3.2.根据ID查询文档

根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把文档id带上。
语法:

GET /{索引库名称}/_doc/{id}
GET /user_info/_doc/1

查看结果:
image.png

3.3.根据ID删除文档

删除使用DELETE请求,同样,需要根据id进行删除:
语法:

DELETE /{索引库名}/_doc/id值

示例:

# 根据id删除数据
DELETE /user_info/_doc/1

3.4.根据ID修改文档

修改有两种方式:

  • 修改全部:直接覆盖原来的文档,实际上当有存在的ID的时候,修改便是**(先删除再添加,版本号进行叠加)**
  • 修改部分:修改文档中的部分字段

3.4.1.修改全部

全量修改是覆盖原来的文档,其本质是:

  • 根据指定的id删除文档
  • 新增一个相同id的文档

注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
语法:

PUT /{索引库名}/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}

示例:

PUT /user_info/_doc/1
{
    "info": "阿里巴巴大老板",
    "email": "my@itcast.cn",
    "name": {
        "firstName": "云",
        "lastName": "马"
    }
}

3.4.2修改部分

增量修改是只修改指定id匹配的文档中的部分字段。
语法:

POST /{索引库名}/_update/文档id
{
    "doc": {
         "字段名": "新的值",
    }
}

示例:

POST /user_info/_update/1
{
  "doc": {
    "email": "ZhaoYun@itcast.cn"
  }
}

3.5.总结

文档操作

  • 创建文档:POST /{索引库名}/_doc/文档id { json文档 }
  • 查询文档:GET /{索引库名}/_doc/文档id
  • 删除文档:DELETE /{索引库名}/_doc/文档id
  • 修改文档:
    • 修改全部:PUT /{索引库名}/_doc/文档id { json文档 } ,不管是多少数据,都会将之前的数据删除,并再次添加
    • 修改部分:POST /{索引库名}/_update/文档id { “doc”: {字段}}

如果我的文章对您有帮助,还请您多多支持我。支付宝帮忙扫一下吧
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

pengkai火火火

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

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

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

打赏作者

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

抵扣说明:

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

余额充值