elasticsearch基础概念、索引库操作、文档操作详解

导读:本篇文章讲解 elasticsearch基础概念、索引库操作、文档操作详解,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、elasticsearch的概述

elasticsearch是一款非常强大的开源搜索引擎,底层是基于lucene来实现的。具备非常多强大功能。

可以帮助用户从海量数据中快速找到需要的内容,是一个海量数据搜索技术。

elasticsearch通常会结合以下几个组件来配置使用:

即:kibanaLogstashBeats

这三个组件加上elasticsearch本身,被称为elastic stackELK),即elastic技术栈的意思。

elastic stackelasticsearch为核心被广泛应用在日志数据分析、实时监控等领域。

elastic stack的各组件作用:

  • kibana:数据可视化

  • elasticsearch:存储、计算、搜索数据

  • LogstashBeats:数据抓取

elasticsearch的优势:

  • 支持分布式,可水平扩展
  • 提供Restful接口,可被任何语言调用

二、elasticsearch中的包含的基础概念

2.1 文档和字段

elasticsearch是面向**文档(Document)**存储的。

文档是数据库中一条数据,文档数据会被序列化为json格式后存储在elasticsearch中。

Json文档中包含了很多的字段(Field),类似于数据库中的列。

2.2 索引和映射

索引(Index):相同类型的文档的集合。

例如:所有用户文档,就可以组织在一起,称为用户的索引。

因此,可以把索引当做数据库中的表。数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。

因此,索引库中就有映射(mapping),映射是索引中文档的字段约束信息,类似表的结构约束。

三、mysql和elasticsearch对比

3.1 基础概念对比

mysql elasticsearch 说明
Table Index 索引库(index),就是文档的集合,类似数据库的表(table)
Row Document 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式
Column Field 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)
Schema Mapping Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)
SQL DSL DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

两者各自的优势:

  • mysql:擅长事务类型操作,可以确保数据的安全和一致性

  • elasticsearch:擅长海量数据的搜索、分析、计算

因此在企业中,往往是两者结合使用:

  • 对安全性要求较高的写操作,使用MySQL实现
  • 对查询性能要求较高的搜索需求,使用elasticsearch实现
  • 两者再基于某种方式,实现数据的同步,保证一致性

3.2 正排索引和倒序索引

倒排索引的概念是基于MySQL这样的正向索引而言的。

2.1 MySQL中的正排索引

正向索引可以简称为索引。正向索引是以关键字为主码,查询时需要遍历每一个文件。

每个文件都对应一个文件ID,文件内容被表示为一串关键词的集合。

具体的来说就是根据id查询,那么直接走索引,查询速度非常快。

但如果是做模糊查询,就只能逐行扫描数据,当数据量超过百万时,查询效率将会非常的低。

2.2 elasticsearch中的倒排索引

1)倒排索引的两个重要概念:

  • 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息

  • 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。

    例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条。

2)倒排索引创建流程:

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

倒排索引是对正向索引的一种特殊处理

3)倒排索引搜索流程:

  • 用户输入条件进行搜索。

  • 对用户输入内容分词,得到词条。

  • 拿着词条在倒排索引中查找,可以得到包含词条的文档id。

  • 拿着文档id到正向索引中查找具体文档。

虽然要先查询倒排索引,再查询正排索引。

但是无论是词条、还是文档id都建立了索引,查询速度非常快!并且无需全表扫描。

2.3 正排索引和倒排索引的区别

  • 正向索引是传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程

  • 倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程

2.4 正排索引和倒排索引的优缺点

正排索引

  • 优点:

    可以给多个字段创建索引

    根据索引字段搜索、排序速度非常快

  • 缺点:

    根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。

倒排索引

  • 优点:

    根据词条搜索、模糊搜索时,速度非常快

  • 缺点:

    只能给词条创建索引,而不是字段

    无法根据字段做排序

四、elasticsearch索引库操作

索引库就类似数据库表,mapping映射就类似表的结构。

要向elasticsearch中存储数据,必须先创建“库”和“表”。

4.1 mapping映射属性

mapping是对索引库中文档的约束,即表结构的统称!

常见的mapping属性包括:

  • type:字段数据类型,常见的简单类型有:

    • 字符串:
      • text(可分词的文本)
      • keyword(精确值:不可分词的文本,例如:品牌、国家、ip地址)
    • 数值:longintegershortbytedoublefloat
    • 布尔:boolean
    • 日期:date
    • 对象:object
    • 地理位置:geo_point(使用逗号分隔存储的经纬度,在定位和搜索附件等功能时非常实用)

    elasticsearch中是没有数组类型的,但是允许一个类型有多个值

    所以integer类型可以写成:[1, 2, 3]

  • index:是否创建(倒排)索引,默认为true

  • analyzer:使用哪种分词器

  • properties:该字段的子字段

  • copy_to:将当前字段拷贝到指定字段

text和keyword详解:

  • text:字段类型是text(并且需要创建索引)则分词器生效,会对内容进行分词,

    先分词然后把分词结果放入倒排索引

  • keyword:如果一个字段类型是keyword(并且需要创建索引),这个字段不分词原样存储到倒排索引

这些是常见的属性,并不是所有的,但足以应对大多数情况。

4.2 创建索引库和索引库中的映射

基本语法:

  • 请求方式:PUT
  • 请求路径:/索引库名称(可以自定义)
  • 请求参数:mapping映射

格式示例:

PUT /myfirst
{
  "mappings": {
    "properties": {
      "address":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email":{
        "type": "keyword",
        "index": false
      },
      "name":{
        "type": "object",
        "properties": {
          "firstName": {
            "type": "keyword"
          },
          "lastName": {
            "type": "keyword"
          }							
        }
      }
    }
  }
}

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

  • address:类型为字符串,需要分词,因此是text

    要参与搜索,因此需要indextrue;分词器为用ik_smart,因为默认分词器无法对中文分词

  • email:类型为字符串,但是不需要分词,因此是数据类型是keyword,且无需分词器;

    不参与搜索,无需创建倒排索引,因此需要indexfalse

  • name:类型为object,需要定义多个子属性

    • name.firstName;类型为字符串,但是不需要分词,因此数据类型是keyword

      需要参与搜索,因此需要创建倒排索引,indextrue;但是无需分词器

    • name.lastName;类型为字符串,但是不需要分词,因此数据类型是keyword

      参与搜索,因此需要创建倒排索引,indextrue;但是无需分词器

copy_to的使用:

PUT /copyto
{
  "mappings": {
    "properties": {
	  "brand":{
        "type": "keyword",
        "copy_to": "all"
      },
      "city":{
        "type": "keyword",
        "copy_to": "all"
      },
      "all":{
        "type": "text",
        "copy_to": "ik_max_word"
      },
    }
  }
}

上面相当于把brand字段和city字段合并到all字段中去。这样就能实现在一个字段中搜索到多个字段的内容。

并且这个合并已经做过优化,并不是直接把各个字段文档值给拷贝到all字段中去。

而是基于all创建倒排索引,所以查询的时候可能看不到all字段,但是搜索的时候却可以根据它来搜索。

这样使用java api查询的时候,可以直接查询all字段,而不用一个个去查询其它字段。

4.3 查询索引库

基本语法

  • 请求方式:GET

  • 请求路径:/索引库名称

  • 请求参数:无

格式示例:

GET /索引库名称

比如要查询上面新增的索引库:

GET /myfirst

4.4 删除索引库

语法:

  • 请求方式:DELETE

  • 请求路径:/索引库名称

  • 请求参数:无

格式:

DELETE /索引库名称

比如要删除上面新增的索引库:

DELETE /myfirst

4.5 修改索引库

倒排索引结构虽然不复杂,但是一旦数据结构改变,就需要重新创建倒排索引,这几乎是灾难。

因此在elasticsearch当中,索引库一旦创建,无法再去修改其中的mapping结构

虽然无法修改mapping中已有的字段,但是允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

语法格式

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

示例:

PUT /myfirst/_mapping
{
  "properties": {
    "age":{
      "type": "integer"
    }
  }
}

_mapping是固定写法

新字段名不能和旧字段名一致,这会让elasticsearch认为你在更新索引库,会直接报错

五、elasticsearch文档操作

5.1 新增文档

语法格式

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

语法示例:

POST /myfirst/_doc/1
{
  "info": "Java开发工程师",
  "email": "123456789@qq.com",
  "name": {
    "firstName": "张",
    "lastName": "肥聪"
  }
}

_doc是固定写法

索引库id最好要加,要不然会随机生成一个

5.2 查询文档

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

语法格式:

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

语法示例:

GET /myfirst/_doc/1

5.3 批量查询文档

GET /hotel/_search

其实就是查询全部的DSL语句

5.4 删除文档

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

语法格式:

DELETE /索引库名称/_doc/id值

语法示例:

// 根据id删除数据
DELETE /myfirst/_doc/1

5.5.修改文档

修改有两种方式:

  • 全量修改:直接覆盖原来的文档
  • 增量修改:修改文档中的部分字段

5.5.1 全量修改

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

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

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

语法格式:

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

语法示例:

PUT /myfirst/_doc/1
{
  "info": "Java开发工程师",
  "email": "978645312@qq.com",
  "name": {
    "firstName": "张",
    "lastName": "三疯"
  }
}

5.5.2 增量修改

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

语法格式:

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

语法示例:

POST /heima/_update/1
{
  "doc": {
    "email": "978645312@qq.com"
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116466.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!