Elasticsearch系列---简单入门实战

概要

本篇主要介绍一下Elasticsearch Document的数据格式,在Java应用程序、关系型数据库建模的对比,介绍在Kibana平台编写Restful API完成基本的集群状态查询,Document最基本CRUD操作示例以及bulk批处理示例。

Document数据格式

Java应用系统的数据模型都是面向对象的,有些对象比较复杂,传统的业务系统,数据需要落地到关系型数据库,在数据库领域模型设计时,会把复杂的POJO对象设计成一对一或一对多的关系,进行扁平化处理,查询的时候,需要多表查询并还原回POJO对象的格式。
Elasticsearch是文档数据库,Document存储的数据结构,可以和POJO保持一致,并且使用JSON格式,这样查询数据时比较方便。

Document文档数据示例:

{
  "fullname" : "Three Zhang",
  "text" : "hello elasticsearch",
  "org": {
      "name": "development",
      "desc": "all member are lovely"
  }
}

Restful API让请求更容易

前面文章有提及Elasticsearch与Kibana搭配使用,Kibana界面的Dev Tools菜单,可以发送Elasticsearch的Restful请求。后续的Restful API请求,如无例外,均是在Kibana平台上执行的。

我们先拿几个查询集群信息的请求来试试

  1. 检查集群的健康状况

GET /_cat/health?v

epoch      timestamp cluster        status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1573626290 14:24:50  hy-application yellow          1         1     1  1    0    0       1             0                  -                 50.3%

从上面能看出node、shard的数量等,还有一个是集群的状态,上面显示的是yellow,为什么是yellow?
集群的状态有green、yellow、red三种,定义如下:

  • green:每个索引的primary shard和replica shard都是active状态的
  • yellow:每个索引的primary shard都是active状态的,但是部分replica shard不是active状态,处于不可用的状态
  • red:不是所有索引的primary shard都是active状态的,部分索引有数据丢失了

我们的示例只启动了一个elasticsearch实例,只有一个node,由于索引默认会使用5个primary shard和5个replica shard,并且同一个node下面的primary shard和replica shard不能分配在一台机器上(容错机制),所有只有1个primary shard被分配和启动了,replica shard没有第二台node去启动,因而是yellow状态。如果想变成green判断,另外启一台node即可。

  1. 查看集群中有哪些索引

GET /_cat/indices?v

health status index                  uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   location               48G_CgE7TiWomlYsyQW1NQ   5   1          3            0       11kb           11kb
yellow open   company_mem            s9DKUeyWTdCj2J8BaFYXRQ   5   1          3            0       15kb           15kb
yellow open   %{[appname]}           ysT9_OibR5eSRu19olrq_w   5   1         32            0    386.5kb        386.5kb
yellow  open   .kibana                4yS67TTOQGOD7l-uMtICOg   1   0          2            0       12kb           12kb
yellow open   tvs                    EM-SvQdfSaGAXUADmDFHVg   5   1          8            0     16.3kb         16.3kb
yellow open   company_org            wIOqfx5hScavO13vvyucMg   5   1          3            0     14.6kb         14.6kb
yellow open   blog                   n5xmcGSbSamYphzI_LVSYQ   5   1          1            0      4.9kb          4.9kb
yellow open   website                5zZZB3cbRkywC-iTLCYUNg   5   1         12            0     18.2kb         18.2kb
yellow open   files                  _6E1d7BLQmy9-7gJptVp7A   5   1          2            0      7.3kb          7.3kb
yellow open   files-lock             XD7LFToWSKe_6f1EvLNoFw   5   1          1            0        8kb            8kb
yellow open   music                  i1RxpIdjRneNA7NfLjB32g   5   1          3            0     15.1kb         15.1kb
yellow open   book_shop              1CrHN1WmSnuvzkfbVCuOZQ   5   1          4            0     18.1kb         18.1kb
yellow open   avs                    BCS2qgfFT_GqO33gajcg_Q   5   1          0            0      1.2kb          1.2kb
  1. 查看node信息

GET /_cat/nodes?v

响应:

ip             heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.17.137           38          68   0    0.08    0.03     0.05 mdi       *      node-1

我们可以看到node的名称。

  1. 创建索引命令

创建名称为"location"的索引

PUT /location?pretty

响应:

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

查看索引,能看到刚刚创建的索引location

health status index                  uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   location               48G_CgE7TiWomlYsyQW1NQ   5   1          3            0       11kb           11kb
yellow open   .kibana                4yS67TTOQGOD7l-uMtICOg   1   0          2            0       12kb           12kb
  1. 删除索引命令

删除名称为"location"的索引

DELETE /location?pretty

再查看索引,刚刚创建的索引location已经删除掉了

health status index                  uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   .kibana                4yS67TTOQGOD7l-uMtICOg   1   0          2            0       12kb           12kb

是不是很简单,交互界面挺友好吧?

入门CRUD操作

介绍document最基本的CRUD操作,以儿童英文歌曲为背景

  1. 新增歌曲

我们设计的儿歌结构包含四个字段:歌名name,歌词content,语言种类language,歌曲时间长length,单位是秒,放在JSON字符串里。
PUT语法:
<REST Verb> /<Index>/<Type>/<ID>
REST Verbs可以是PUT、POST、DELETE,后斜杠后的内容分别是索引名、类型名、ID。

请求如下:

PUT /music/children/1
{
    "name": "gymbo",
    "content": "I hava a friend who loves smile, gymbo is his name",
    "language": "english",
    "length": "75"
}

响应内容包含索引名、类型名、ID值,version版本号(乐观锁控制),结果类型(created/updated/deleted三种),shard信息等,如果新增时该索引不存在,会自动创建索引,索引名即请求时指定的那个,document里面的field类型,就根据elasticsearch定义的自动映射类型,并且每个field都会建立倒排索引,让其可以被搜索到。

total和successful为什么数据不相等?
新增document时,会往primary shard和replica shard分别写入document,但由于只有一个node,replica未启动,所以总共写入2次,primary shard成功,数量是1。failed只记录primary shard写入失败的情况。

响应如下:

{
  "_index": "music",
  "_type": "children",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}
  1. 修改歌曲
    修改document有两种方式,一种是增量修改,只修改指定的field,另一种是全量替换文档,原有的信息全部被替换掉

    • 增量修改length的值,注意是POST请求,并且尾部有_update,doc是固定写法,请求如下:

      POST /music/children/1/_update
      {
      "doc": {
      "length": "76"
      }
      }

响应:

{
  "_index": "music",
  "_type": "children",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
  • 全量替换文档,请求如下:
PUT /music/children/1
{
    "name": "gymbo",
    "content": "I hava a friend who loves smile, gymbo is his name",
    "language": "english",
    "length": "77"
}

响应:

{
  "_index": "music",
  "_type": "children",
  "_id": "1",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

细心的童鞋可以,全量替换文档的语法和创建索引是一样的,对!就是同一个语法 ,是创建还是更新取决于上面的ID存不存在,不存在做创建,存在做更新,更新成功version+1,但这种全量替换有个不好的地方,必须带上完整的属性,否则未声明属性就没有了。

想想要使用这个语法的场景:先GET所有的属性,然后把要更新的属性更新上,再调用全量替换的更新语法。实际上这种做法不多,原因不外乎两个:操作复杂,要先查询后更新;报文过大(相对于增量更新)。所以企业研发一般使用增量方式做document更新。

  1. 查询歌曲

查询语句:GET /music/children/1

_source即为JSON的内容,查询结果:

{
  "_index": "music",
  "_type": "children",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "gymbo",
    "content": "I hava a friend who loves smile, gymbo is his name",
    "language": "english",
    "length": "75"
  }
}
  1. 删除歌曲

删除语句:DELETE /music/children/1

响应结果:

{
  "_index": "music",
  "_type": "children",
  "_id": "1",
  "_version": 4,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}

bulk批处理

上一节提及的增删改操作,是针对单个document的,Elasticsearch还有一个批处理命令,可以批量执行这些操作。

  1. bulk的基本语法示例
    还是以上面的儿歌为案例背景

    POST /music/children/_bulk
    {"index":{"_id":"1"}}
    {"name": "gymbo", "content": "I hava a friend who loves smile, gymbo is his name", "language": "english", "length": "75"}
    {"create":{"_id":"2"}}
    {"name": "wake me, shark me", "content": "don‘t let me sleep too late", "language": "english", "length": "55"}
    { "update": {"_id": "2", "retry_on_conflict" : 3} }
    { "doc" : {"content" : "don‘t let me sleep too late, gonna get up brightly early in the morning"} }
    { "delete": {"_id": "3" }}

可以把多条命令放在一起执行,如果一个bulk请求内有不同的index和type,可以把index和type也可以写在body json里,每一个操作要两个json串:

{"action": {"metadata"}}
{"data"}

delete例外,它只需要1个json串就可以了

action的类型有以下几种:

  • index:普通的PUT操作,ID不存在时创建document,ID存在时做全量替换
  • create:强制创建,等同于PUT /index/type/id/_create命令
  • update:执行的增量修改操作
  • delete:删除document操作
  1. bulk注意事项
    bulk api有严格的语法要求,每个json串内不能换行,同时每个json串之间必须要有一个换行,否则会报语法错误。
    bulk既然是多条命令批量执行,遇到错误怎么办?会中断吗?
    如果bulk请求内有命令执行错误,会直接跳过,继续执行下一条,同时在响应报文里会对每条命令的结果分别展示,正确的就展示正确的结果,错误的会相应提示错误日志。
  2. bulk的性能问题
    bulk既然是批处理,那bulk size与最佳性能肯定存在一定的联系,bulk请求的内存会先加载到内存里,bulk的请求取决于命令的条数和每个命令内容的多少,与性能的关系示例图(表达概念,数据不具备参考性)如下:

bulk性能优化的目标就是找到这个拐点,需要反复尝试一个最佳的size,跟具体的业务数据特性,并发量有关,常见的设置范围一般是1000-5000之间,bulk请求的大小控制在5-15MB之间(仅供参考)。

小结

本篇简单介绍了一下document的数据格式,并顺带讲解了一下Elasticsearch集群红黄绿三种状态的判定标准,重点是在kibana平台演示的CRUD小案例和bulk批处理示例,最为基础,可以多花一些时间熟悉熟悉。

专注Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区
可以扫左边二维码添加好友,邀请你加入Java架构社区微信群共同探讨技术

原文地址:https://blog.51cto.com/2123175/2482625

时间: 2024-10-05 05:50:08

Elasticsearch系列---简单入门实战的相关文章

ElasticSearch搜索引擎的入门实战

1.ElasticSearch简介 引用自百度百科: ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便. 我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的.我们希望搜索解决方案要运行速度快,

1. VIM 系列 - 简单入门,拾起兴趣

目录 1. 认识模式 1.1 正常模式 1.2 插入模式 1.3 命令模式 1.4 可视模式 2. 常用快捷键 1. 认识模式 vim 一共有四种模: 1. 正常模式 2. 插入模式 3. 命令模式 4. 可视模式 1.1 正常模式 vim 打开一个文件时,处于正常模式. 正常模式一般用来浏览文件,也可进行复制.粘贴.删除等操作. 浏览文件时,可以采用一些快捷键在文本中进行跳转. 注:无论当前处于什么模式,按下 ESC 键 都会回到正常模式. 1.2 插入模式 插入模式:在正常模式下,按下(i/

Elasticsearch系列---补充几个知识点

概要 bulk api有趣的json格式 前面<简单入门实战>一节中,有介绍bulk的使用示例,大家一定很奇怪,还有这么有趣的JSON格式,必须严格照他的换行来做,我想把JSON搞得美观可读性好一点,居然给我报错! {"action": {"meta"}}\n {"data"}\n {"action": {"meta"}}\n {"data"}\n 它为什么要这样规定? 我们

Spark入门实战系列--8.Spark MLlib(上)--机器学习及SparkMLlib简介

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.机器学习概念 1.1 机器学习的定义 在维基百科上对机器学习提出以下几种定义: l“机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经验学习中改善具体算法的性能”. l“机器学习是对能通过经验自动改进的计算机算法的研究”. l“机器学习是用数据或以往的经验,以此优化计算机程序的性能标准.” 一种经常引用的英文定义是:A computer program is said

Spark入门实战系列--9.Spark图计算GraphX介绍及实例

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.GraphX介绍 1.1 GraphX应用背景 Spark GraphX是一个分布式图处理框架,它是基于Spark平台提供对图计算和图挖掘简洁易用的而丰富的接口,极大的方便了对分布式图处理的需求. 众所周知·,社交网络中人与人之间有很多关系链,例如Twitter.Facebook.微博和微信等,这些都是大数据产生的地方都需要图计算,现在的图处理基本都是分布式的图处理,而并非单机处理.Spark

Spark入门实战系列--5.Hive(上)--Hive介绍及部署

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.Hive介绍 1.1 Hive介绍 Hive是一个基于Hadoop的开源数据仓库工具,用于存储和处理海量结构化数据.它是Facebook 2008年8月开源的一个数据仓库框架,提供了类似于SQL语法的HQL语句作为数据访问接口,Hive有如下优缺点: l  优点: 1.Hive 使用类SQL 查询语法, 最大限度的实现了和SQL标准的兼容,大大降低了传统数据分析人员学习的曲线: 2.使用JDBC

Spark入门实战系列--8.Spark MLlib(下)--机器学习库SparkMLlib实战

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.MLlib实例 1.1 聚类实例 1.1.1 算法说明 聚类(Cluster analysis)有时也被翻译为簇类,其核心任务是:将一组目标object划分为若干个簇,每个簇之间的object尽可能相似,簇与簇之间的object尽可能相异.聚类算法是机器学习(或者说是数据挖掘更合适)中重要的一部分,除了最为简单的K-Means聚类算法外,比较常见的还有层次法(CURE.CHAMELEON等).网

Spark入门实战系列--6.SparkSQL(下)--Spark实战应用

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送–Spark入门实战系列>获取 1 运行环境说明 1.1 硬软件环境 主机操作系统:Windows 64位,双核4线程,主频2.2G,10G内存 虚拟软件:VMware? Workstation 9.0.0 build-812388 虚拟机操作系统:CentOS 64位,单核 虚拟机运行环境: JDK:1.7.0_55 64位 Hadoop:2.2.0(需要编译为64位) Scala:2.10.4 Spark:1.1.0(需要编译)

Spark入门实战系列--6.SparkSQL(上)--SparkSQL简介

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.SparkSQL的发展历程 1.1 Hive and Shark SparkSQL的前身是Shark,给熟悉RDBMS但又不理解MapReduce的技术人员提供快速上手的工具,Hive应运而生,它是当时唯一运行在Hadoop上的SQL-on-Hadoop工具.但是MapReduce计算过程中大量的中间磁盘落地过程消耗了大量的I/O,降低的运行效率,为了提高SQL-on-Hadoop的效率,大量的