对比mysql增删查改,理解elasticsearch[6.7.2版本]操作

ES基础概念

  • 索引(index)
  • 一个索引可以理解成一个关系型数据库
  • 类型(type)
  • 一种type就像一类表,比如user表,order表。

注意
es 5.x中一个index可以有多种type
es6.x中一个index只能有一种type
es7.x以后已经移除type这个概念

  • 映射(mapping)

mapping定义了每个字段的类型等信息。相当于关系型中的表结构

  • 文档(document)

一个document相当于关系型数据库中的一行记录

  • 字段

相当于关系型数据库表的字段

  • 集群

集群由一个或多个节点组成,一个集群有一个默认名称“elasticsearch”

  • 节点

集群的节点,一台机器或者一个进程

  • 分片和副本

副本是分片的副本。分片有主分片(primary Shard)和副本分片(replica Shard)之分
一个index数据在物理上被分布在多个主分片中,每个主分片只存放部分数据
每个主分片可以有多个副本,叫副本分片,是主分片的复制

1.索引文档结构

像上面基础概念所讲的,映射mapping就是mysql中的表结构。在mysql定义表结构时,我们使用以下的sql语句。首先,创建一个主键自增的表。因为es中的_id元数据也是默认采用自动生成的。

  • 定义mysql表结构
CREATE TABLE `testone` (
  `id` int(50) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `descs` varchar(255) DEFAULT NULL,
  `birthday` datetime DEFAULT NULL,
  `address` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 定义es结构体
PUT http://localhost:9200/testone
{
  "mappings": {
    "_doc": {
      "properties": {
        "id": {
          "type": "keyword"
        },
        "name": {
          "type": "text"
        },
        "age": {
          "type": "integer"
        },
        "descs": {
          "type": "text"
        },
        "birthday": {
          "type": "date",
          "format": "yyyy-MM-dd HH:mm:ss"
        }
      }
    }
  }
}
  • 查看结构体
 GET http://localhost:9200/testone/_doc/_mapping

2.修改文档结构

在定义完文档结构后,可以添加字段,改变文档结构。无论是es这种非结构数据存储还是关系型存储的mysql,都是不建议减少字段的。

  • mysql中修改表结构
ALTER TABLE testone add address VARCHAR(255)
  • 修改es文档结构
PUT http://localhost:9200/testone/_mapping/_doc
{
  "properties": {
    "address": {
      "type": "text"
    }
  }
}

3.重新索引

es不能修改字段类型的,如果非要如此操作,可以使用重新索引,将testone的数据索引到testwo,testone的数据可以传送到testwo中。

  • 修改mysql字段类型
ALTER TABLE testone MODIFY address VARCHAR(500)
  • 修改es字段类型,需要重新索引的操作创建testwo索引,定义最新的结构体。将es中age的字段类型进行修改。integer --> keword
 PUT http://localhost:9200/testwo
{
  "mappings": {
    "_doc": {
      "properties": {
        "id": {
          "type": "keyword"
        },
        "name": {
          "type": "text"
        },
        "age": {
          "type": "keyword"
        },
        "descs": {
          "type": "text"
        },
        "birthday": {
          "type": "date",
          "format": "yyyy-MM-dd HH:mm:ss"
        }
      }
    }
  }
}
  • 重新索引
POST http://localhost:9200/_reindex
{
  "source": {
    "index": "testone"
  },
  "dest": {
    "index": "testwo"
  }
}

重新索引后可以将之前的索引删除

4.创建一个文档

创建文档在mysql就是新增一条记录。

  • mysql 新增记录
insert into testone(name,age,descs,birthday,address)
VALUES ('lyc','25','palyer','2010-02-20 20:00:00','beijing')

在es中新增一条记录时,id可以是es默认的自增模式,也是可以自己指定id值去创建。

  • es自增id式新增
POST http://localhost:9200/testone/_doc
{
  "name": "lyc",
  "age": "25",
  "descs": "palyer",
  "birthday": "2010-02-20 20:00:00",
  "address": "beijing"
}
  • es指定id式新增
POST http://localhost:9200/testone/_doc/1
{
  "name": "test",
  "age": "25",
  "descs": "palyer",
  "birthday": "2010-02-20 20:00:00",
  "address": "beijing"
}

若是put请求,必须指定id,post请求也可以添加自定义id

5.更新一个文档

文档在Elasticsearch中是不可变的——我们不能修改他们。如果需要更新已存在的文档,可以使用上文所讲的重建索引(reindex) 或者替换掉它。
更新文档时,在Elasticsearch内部,会将之前的文档标记旧文档并删除,然后添加了一个完整的新文档。旧版本文档不会立即消失,但你也不能去访问它。Elasticsearch会在你继续索引更多数据时清理被删除的文档。这个API 似乎 允许你修改文档的局部,但事实上Elasticsearch遵循与之前所说完全相同的过程,这个过程如下:

  • 从旧文档中检索JSON
  • 修改它
  • 删除旧文档
  • 索引新文档

唯一的不同是update API完成这一过程只需要一个客户端请求既可,不再需要get和index请求了

6.查询

6.1 空查询

空查询就是不加查询参数的查询,将表或索引中的记录都查询出来。

在mysql中如果我们不指定任何查询参数,将会查询出所有表记录。而在es中为了效率问题,默认只会查询出前10条记录

  • mysql
select * from testone 
  • es
GET http://localhost:9200/testone/_doc/_search
{}
  • 以下解释返回结构体中的参数意义
hits

响应中最重要的部分是hits,它包含了total字段来表示匹配到的文档总数,hits数组还包含了匹配到的前10条数据。

hits数组中的每个结果都包含_index_type和文档的_id字段,被加入到_source字段中这意味着在搜索结果中我们将可以直接使用全部文档。这不像其他搜索引擎只返回文档ID,需要你单独去获取文档。

每个节点都有一个_score字段,这是相关性得分(relevance score),它衡量了文档与查询的匹配程度。默认的,返回的结果中关联性最大的文档排在首位;这意味着,它是按照_score降序排列的。这种情况下,我们没有指定任何查询,所以所有文档的相关性是一样的,因此所有结果的_score都是取得一个中间值1

max_score指的是所有文档匹配查询中_score的最大值。

took

took告诉我们整个搜索请求花费的毫秒数。

shards

_shards节点告诉我们参与查询的分片数(total字段),有多少是成功的(successful字段),有多少的是失败的(failed字段)。通常我们不希望分片失败,不过这个有可能发生。如果我们遭受一些重大的故障导致主分片和复制分片都故障,那这个分片的数据将无法响应给搜索请求。这种情况下,Elasticsearch将报告分片failed,但仍将继续返回剩余分片上的结果。

timeout

time_out值告诉我们查询超时与否。一般的,搜索请求不会超时。如果响应速度比完整的结果更重要,你可以定义timeout参数为10或者10ms(10毫秒),或者1s(1秒)

 GET http://localhost:9200/testone/_doc?timeout=10ms

Elasticsearch将返回在请求超时前收集到的结果。
超时不是一个断路器(circuit breaker)

6.2 多索引,多类别查询

在mysql中多表查询需要用到关联,则关联查询时需要两个表有逻辑关联,如果是两个不相干,互相独立不依赖的表是无法做关联查询的。
而在es中可以多索引多类别的查询

GET http://localhost:9200/testone,ca_bm_blog_message/_doc,_doc/_search

翻译一下,查询testone和ca_bm_blog_message索引下的testone的_doc类别和ca_bm_blog_message的_doc类型。格式上为

  • 索引1,索引2/类别1,类别2/_search

6.3 查询分页

  • mysql中的查询分页
select * from testone limit 0,10
select * from testone limit 5,20
  • es中查询默认是只会返回10条数据。如果需要查询更多需要加size和from参数
  • size: 结果数,默认10
  • from: 跳过开始的结果数,默认0
 testone/_search?size=10
 testone/_search?size=20&from=5 

应该当心分页太深或者一次请求太多的结果。结果在返回前会被排序。但是记住一个搜索请求常常涉及多个分片。每个分片生成自己排好序的结果,它们接着需要集中起来排序以确保整体排序正确。

在集群系统中深度分页

为了理解为什么深度分页是有问题的,让我们假设在一个有5个主分片的索引中搜索。当我们请求结果的第一页(结果1到10)时,每个分片产生自己最顶端10个结果然后返回它们给请求节点(requesting node),它再排序这所有的50个结果以选出顶端的10个结果。
现在假设我们请求第1000页——结果10001到10010。工作方式都相同,不同的是每个分片都必须产生顶端的10010个结果。然后请求节点排序这50050个结果并丢弃50040个!

6.4 简易查询

search API有两种表单:一种是“简易版”的查询字符串(query string)将所有参数通过查询字符串定义,另一种版本使用JSON完整的表示请求体(request body),这种富搜索语言叫做结构化查询语句(DSL)

  • mysql中的条件查询
select * from testone where name = 'zst'
  • es中简易查询
GET http://localhost:9200/testone/_search?q=%2Bname%3Azst

注意 参照URL编码表

codedecode
%2B+
%3A:
%2D-

decode之后是这样:


GET http://localhost:9200/testone/_search?q=+name:zst

"+“前缀表示语句匹配条件必须被满足。类似的”-"前缀表示条件必须不被满足。所有条件如果没有+或-表示是可选的——匹配越多,相关的文档就越多。

在不指定查询字段匹配时,如

GET http://localhost:9200/testone/_search?q=palyer

es会把文档中所有字段组合生成一个新的字段_all,将字段文本都合成这一个新字段(此处只是类比)
然后所有出符合条件的文档记录。

"name": "zst",
"age": "25",
"desc": "palyer",
"birthday": "2000-02-20 20:00:00",
"address": "beijing"

类似于,_all : “zst 25 palyer 2000-02-20 20:00:00 beijing”
当查询参数过多,查询条件组合过多,在简易查询中就不易读了

GET http://localhost:9200/testone/_search?q=+name:(test zst) +birthday:>2014-09-10
 -address:shanghai

翻译成sql就是

select * from testone where name in ('test','zst') and birthday > '2020-01-10 ' and address<>'shanghai'

此时就需要使用JSON完整的表示请求体(request body)

未完待续。。。下节将字段类型和分词对查询的影响

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值