码迷,mamicode.com
首页 > 其他好文 > 详细

ELK入门及基本使用

时间:2020-06-12 20:31:17      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:永久   cti   amp   概念   查询条件   sel   null   还需要   linu   

预备知识-Restful

起源

  在没有前后端分离概念之前,一个网站的完成总是“all in one”,在这个阶段,页面、数据、渲染全部在服务端完成,这样做的最大的弊端是后期维护,扩展极其痛苦,开发人员必须同时具备前后端知识。于是后来慢慢的兴起了前后端分离的思想:即后端负责数据编造,而前端则负责数据渲染,前端静态页面调用指定 api 获取到有固定格式的数据,再将数据展示出来,这样呈现给用户的就是一个”动态“的过程。

  而关于 api 这部分的设计则成了一个问题。如何设计出一个便于理解,容易使用的 api 则成了一个问题,而所谓的 RESTful 就是用来规范我们的 API 的一种约束。

REST

  作为 REST,其实是 Representational State Transfer(表象层状态转变)三个单词的缩写,它由 Roy Fielding(Fielding 是 HTTP 协议(1.0 版和 1.1 版)的主要设计者、Apache 服务器软件的作者之一、Apache 基金会的第一任主席)于2000 年论文中提出,他在论文中提到:"我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST 指的是一组架构约束条件和原则。"如果一个架构符合 REST 的约束条件和原则,我们就称它为 RESTful 架构。

  要理解 RESTful 架构,最好的方法就是去理解 Representational StateTransfer 这个词组到底是什么意思,它的每一个词代表了什么涵义。如果你把这个名称搞懂了,也就不难体会 REST 是一种什么样的设计。

资源(Resources)

REST 的名称"表现层状态转化"中,省略了主语。"表现层"其实指的是"资源"(Resources)的"表现层"。

所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。

要让一个资源可以被识别,需要有个唯一标识, Web 中这个唯一标识就是URI(Uniform Resource Identifier)。

URI 既可以看成是资源的地址,也可以看成是资源的名称。如果某些信息没有使用 URI 来表示,那它就不能算是一个资源,只能算是资源的一些信息而已。

你可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI。

要获取这个资源,访问它的 URI 就可以,因此 URI 就成了每一个资源的地址或独一无二的识别符。

所谓"上网",就是与互联网上一系列的"资源"互动,调用它的 URI。

 

URI 设计技巧

1、使用 _  - 来让 URI 可读性更好

曾经 Web 上的 URI 都是冰冷的数字或者无意义的字符串,但现在越来越多的网站使用_或-来分隔一些单词, URI 看上去更为人性化。例如国内比较出名的开源中国社区,它上面的新闻地址就采用这种风格,如

http://www.oschina.net/news/38119/oschina-translate-reward-plan。

2、使用 / 来表示资源的层级关系

例如上述/git/git/commit/e3af72cdafab5993d18fae056f87e1d675913d08就表示了一个多级的资源,指的是 git 用户的 git 项目的某次提交记录,又例如/orders/2012/10 可以用来表示 2012 年 10 月的订单记录。

3、使用 ? 用来过滤资源

很多人只是把?简单的当做是参数的传递,很容易造成 URI 过于复杂、难以理解。可以把?用于对资源的过滤,例如/git/git/pulls 用来表示 git 项目的所有推入请求,/pulls?state=closed 用来表示 git 项目中已经关闭的推入请求,这种 URL 通常对应的是一些特定条件的查询结果或算法运算结果。

; 可以用来表示同级资源的关系

有时候我们需要表示同级资源的关系时,可以使用,或;来进行分割。例如哪天github 可以比较某个文件在随意两次提交记录之间的差异,或许可以使用/git/git

/block-sha1/sha1.h/compare/e3af72cdafab5993d18fae056f87e1d675913d08;bd63e61bdf38e872d5215c07b264dcc16e4febca 作为 URI。不过,现在 github 是使用…来做这个事情的,例如/git/git/compare/master…next。

4、URI 不应该包含动词

因为"资源"表示一种实体,所以应该是名词,URI 不应该有动词,动词应该放在 HTTP 协议中。

举例来说,某个 URI 是/posts/show/1,其中 show 是动词,这个 URI 就设计错了,正确的写法应该是/posts/1,然后用 GET 方法表示 show。

如果某些动作是 HTTP 动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户 1向账户 2汇款 500 元,错误的 URI 是:

POST /accounts/1/transfer/500/to/2

正确的写法是把动词 transfer 改成名词 transaction,资源不能是动词,但是可以是一种服务。

5、URI 中不宜加入版本号

例如:

http://www.example.com/app/1.0/foo

http://www.example.com/app/1.1/foo

http://www.example.com/app/2.0/foo

 

因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个 URI。版本号可以在 HTTP 请求头信息的 Accept 字段中进行区分。

 

表现层(Representation)

  "资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。

比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式;图片可以用 JPG 格式表现,也可以用 PNG格式表现。

URI 只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,URI 应该只代表"资源"的位置。它的具体表现形式,应该在 HTTP 请求的头信息中用 Accept 和 Content-Type 字段指定,这两个字段才是对"表现层"的描述。

 

状态转化(State Transfer)

  访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。

互联网通信协议 HTTP 协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

客户端用到的手段,目前来说只能是 HTTP 协议。具体来说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE 用来删除资源。GET、PUT 和 DELETE 请求都是幂等的,无论对资源操作多少次,结果总是一样的, POST 不是幂等的。

 

什么是 RESTful 架构

  综合上面的解释,我们总结一下什么是 RESTful 架构:

  1.架构里,每一 URI 代表一种资源;

  2.客户端和服务器之间,传递这种资源的某种表现层;

  3.客户端通过四个 HTTP 动词(get、post、put、delete),对服务器端资源进行操作,实现”表现层状态转化”。

  注意:REST 架构风格并不是绑定在 HTTP 上,只不过目前 HTTP 是唯一与 REST相关的实例。所以我们这里描述的 REST 也是通过 HTTP 实现的 REST。

 

辨析 URI、URL、URN

RFC 3986 中是这样说的:

A Uniform Resource Identifier (URI) 是一个紧凑的字符串用来标示抽象或物理资源。一 URI 可以进一步被分为定位符、名字或两者都是. 术语“Uniform Resource Locator”(URL) 是 URI 的子集, 除了确定一个资源,还提供一种定位该资源的主要访问机制。

所以,URI = Universal Resource Identifier 统一资源标志符,包含 URL和URN,支持的协议有 http、https、ftp、mailto、magnet、telnet、data、file、nfs、gopher、ldap 等,java 还大量使用了一些非标准的定制模式, rmi,jar、jndi 和 doc,来实现各种不同用途。

URL = Universal Resource Locator 统一资源定位符,URL 唯一地标识一个资源在 Internet 上的位置。不管用什么方法表示,只要能定位一个资源,就叫URL。

URN = Universal Resource Name 统一资源名称,URN 它命名资源但不指定如何定位资源,比如:只告诉你一个人的姓名,不告诉你这个人在哪。

对于一个资源来说,URN 就好比他的名字, URL 就好比是资源的街道住址。

换句话说,URN 标识了一个资源项目, URL 则提供了一种找到他的方法。

比如同时指定基本的获取机制和网络位置。举个例子,

http://example.org/wiki/Main_Page,指向了一个被识别为/wike/Main_Page的资源,这个资源的表现形式是 HTML 和相关的代码。而获取这个资源的方法是在网络中从一个名为 example.org 的主机上,通过 HTTP( Hypertext TransferProtocol)获得。

URN 则是一种在特定的名称空间中通过通过名字来标识资源的 URI。当讨论一种资源而不需要知道它的位置或者如何去获得它的时候,就可以使用 URN。

例如, International Standard Book Number (ISBN)系统中,* ISBN

0-486-27557-4 用来指定莎士比亚的作品《罗密欧与朱丽叶》的一个特定版本。

指示这一版本的 URN 是 urn:isbn:0-486-27557-4*,但是如果想要获得这个版本的书,就需要知道它的位置,这样就必须知道它的 URL。

 

什么是 ELK

为什么需要 ELK

官网的说法:Elasticsearch 是一个开源的分布式 RESTful 搜索和分析引擎,能够解决越来越多不同的应用场景。

看一个应用场景,常见的 WEB 应用日志分析。一般我们会怎么做?

登录到每台服务器上,直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。

这个时候我们希望集中化的日志管理,所有服务器上的日志收集汇总。常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问。

这样对于大型系统来说,都是一个分布式部署的架构,不同的服务模块部署在不同的服务器上,问题出现时,大部分情况需要根据问题暴露的关键信息,定位到具体的服务器和服务模块,构建一套集中式日志系统,可以提高定位问题的效率。

一个完整的集中式日志系统,需要包含以下几个主要特点:

收集-能够采集多种来源的日志数据

传输-能够稳定的把日志数据传输到中央系统

存储-如何存储日志数据分析-可以支持

UI 分析警告-能够提供错误报告,监控机制

ELK就是这样一整套解决方案,并且都是开源软件,之间互相配合使用,完美衔接,高效的满足了很多场合的应用,而不仅仅是日志分析。

什么是 ELK

ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件

Elasticsearch是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

Logstash 主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。一般工作方式为 c/s 架构,client端安装在需要收集日志的主机上,server端负责将收到的各节点日志进行过滤、修改等操作在一并发往 elasticsearch上去。

Kibana 也是一个开源和免费的工具,Kibana 可以为 Logstash 

ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。

新增了一个 Beats 系列组件,它是一个轻量级的日志收集处理工具(Agent),Beats 占用资源少,适合于在各个服务器上搜集日志或信息后传输给 Logstash。

加入 Beats 系列组件后,官方名称就变为了 Elastic Stack,产品如下:

技术图片

安装,启动和 HelloWorld

环境和安装

运行环境为 Linux,演示服务器操作系统版本情况如下:

 技术图片

因为 Elastic Stack中主要组件都是用 Java 写的,所以操作系统上还应该安装好 Java,本次以 Elasticsearch 7 版本为主,所以,需要安装 JDK1.8 以上

 技术图片

而 Elastic Stack系列产品我们可以到 Elastic的官网上去下载:

https://www.elastic.co/cn/downloads

 技术图片

选择 7.7.0版本为本次版本,从具体的下载页面可以看到 Elastic Stack支持各种形式的安装。

技术图片

 

 

选择以免安装的压缩包的形式。下载后上传到服务器解压缩即可运行。

 技术图片

运行

  Elasticsearch 默认不允许用 root用户运行,会报错,而且从服务器安全的角度来说,也不应该以 root用户来做日常工作,因此我们新建一个用户 elk并以elk用户登录。

Elasticsearch

  用 tar -xvf命令解压压缩包elasticsearch-7.7.0-linux-x86_64.tar.gzip后进入elasticsearch-7.7.0文件夹中的 bin文件夹,并执行命令./elasticsearch。

待启动完成.....

 技术图片

 

 

 技术图片

输入 curl http://localhost:9200

显示:

技术图片

表示Elasticsearch运行成功了,我们试着在本地浏览器进行访问

 技术图片

 

 

 

却显示“拒绝了我们的连接请求”,因此我们还需要配置一下 Elasticsearch以允许我们进行外网访问,进入 elasticsearch-7.7.0下的 config目录,编辑elasticsearch.yml文件,删除 network.host前的#字符,并写入服务器的地址并保存。

技术图片

再次运行,但是这次却出了错

技术图片

从错误提示我们可以知道,还需对 Elasticsearch配置做适当修改,重新编辑elasticsearch.yml文件,并做如下修改:

技术图片

 

 

 技术图片

再次启动,并在浏览器中访问

技术图片

显示 Elasticsearch运行并访问成功!

我们知道,Elasticsearch提供的是 restful风格接口,我们用浏览器访问不是很方便,除非我们自行编程访问 restful接口。这个时候,就可以用上 Kibana ,它已经为我们提供了友好的 Web 界面,方便我们后面对 Elasticsearch的学习。

接下来我们安装运行 Kibana。

Kibana

同样用 tar -xvf命令解压压缩包,进入解压后的目录。为了方便我们的访问和连接 Elasticsearch,也需要进入 Kibana的 config 目录对 Kibana 进行配置

 技术图片

然后进入 Kibana的 bin 目录运行./kibana,kibana因为是用 node.js 编写的,所以启动和运行较慢,需要等待一段时间:

技术图片

 

 

 

从提示我们可以看出,kibana的访问端口是 5601,我们依然在本地浏览器中访问:

技术图片

 

 

 

等候几分钟以后,就会进入 kibana的主界面

技术图片

 

 

 

TIPS:如何检测系统中是否启动了 kibana

我们一般会用ps -ef来查询某个应用是否在 Linux系统中启动,比如Elasticsearch,

我们用 ps -ef|grep java 或者 ps -ef|grep elasticsearch均可

技术图片

但是当我们尝试 ps -ef|grep kibana,却是不行的

技术图片

因为 kibana  node 写的,所以 kibana 运行的时候是运行在 node 里面,我们要查询的话,只能 ps -ef|grep node

技术图片

或者使用 netstat -tunlp|grep 5601

技术图片

 

 

 

因为我们的kibana开放的端口是5601,所以看到5601端口被 Listen (监听),说明 kibana启动成功。

附:netstat参数说明:

  -t (tcp)仅显示 tcp相关选项

  -u (udp)仅显示 udp相关选项

  -n 拒绝显示别名,能显示数字的全部转化成数字。

  -l 仅列出有在 Listen (监听) 的服務状态

  -p 显示建立相关链接的程序名

更多 netstat的相关说明,自行查阅 Linux手册

HelloWorld

点击面板中的“Dev Tools”按钮,进入 Dev 工具,开始我们的 Elasticsearch初次访问之旅。

技术图片

 

 

 

创建索引

在左边命令窗口中输入 put enjoy_test,并点击相关按钮 ,于是看到右

边的结果窗口中 es给我们返回了处理结果,表示我们在 es中创建索引成功。

技术图片

 

 

 

查看索引

要查看我们刚刚创建的索引,执行“get enjoy_test”

技术图片

添加文档

往这个索引中添加文档,执行:

PUT /enjoy_test/_doc/1

{

"msg":"Hello World!"

}

技术图片

查看文档

查询我们刚刚加入的文档,执行“get /enjoy_test/_doc/1”

技术图片

 

 

 

Elasticsearch 基本原理和概念

 

从上面的例子中,我们看到了很多熟悉又陌生的概念,比如索引、文档等等。这些概念和我们平时看到的数据库里的比如索引有什么区别呢?

举个例子,现在我们要保存唐宋诗词,数据库中我们们会怎么设计?诗词表我们可能的设计如下:

朝代

作者

诗词年代

标题

诗词全文

李白

 

静夜思

床前明月光,疑是地上霜。举头望明月,低头思故乡。

李清照

 

如梦令

常记溪亭日暮,沉醉不知归路,兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

….

….

….

…….

要根据朝代或者作者寻找诗,都很简单,比如“select 诗词全文 from 诗词表where作者=‘李白’”,如果数据很多,查询速度很慢,怎么办?我们可以在对应的查询字段上建立索引加速查询。

但是如果我们现在有个需求:要求找到包含“望”字的诗词怎么办?用

“select 诗词全文 from 诗词表 where 诗词全文 like‘%望%’”,这个意味着

要扫描库中的诗词全文字段,逐条比对,找出所有包含关键词“望”字的记录,。

基本上,数据库中一般的 SQL 优化手段都是用不上的。数量少,大概性能还能接受,如果数据量稍微大点,就完全无法接受了,更何况在互联网这种海量数据的情况下呢?

怎么解决这个问题呢,用倒排索引。

倒排索引 Inverted index

比如现在有:

  蜀道难(唐)李白 蜀道之难难于上青天,侧身西望长咨嗟。

  静夜思(唐)李白 举头望明月,低头思故乡。

  春台望(唐)李隆基 暇景属三春,高台聊四望。

  鹤冲天(宋)柳永 黄金榜上,偶失龙头望。明代暂遗贤,如何向?未遂风云便,争不恣狂荡。何须论得丧?才子词人,自是白衣卿相。烟花巷陌,依约丹青屏障。

  幸有意中人,堪寻访。且恁偎红翠,风流事,平生畅。青春都一饷。忍把浮名,换了浅斟低唱!

都有望字,于是我们可以这么保存

序号

关键字

蜀道难

静夜思

春台望

鹤冲天

1

 

 

 

 

 

 

如果查哪个诗词中包含上,怎么办,上述的表格可以继续填入新的记录

序号

关键字

蜀道难

静夜思

春台望

鹤冲天

1

2

 

 

其实,上述诗词的中每个字都可以作为关键字,然后建立关键字和文档之间的对应关系,也就是标识关键字被哪些文档包含。

所以,倒排索引就是,将文档中包含的关键字全部提取处理,然后再将关键字和文档之间的对应关系保存起来,最后再对关键字本身做索引排序。用户在检索某一个关键字是,先对关键字的索引进行查找,再通过关键字与文档的对应关系找到所在文档。

在存储在关系型数据库中的数据,需要我们事先分析将数据拆分为不同的字段,而在 es 这类的存储中,需要应用程序根据规则自动提取关键字,并形成对应关系。

这些预先提取的关键字,在全文检索领域一般被称为 term(词项),文档的词项提取在 es 中被称为文档分析,这是全文检索很核心的过程,必须要区分哪些是词项,哪些不是,比如很多场景下,apple和 apples 是同一个东西,望和看其实是同一个动作。

Elasticsearch 基本概念

Elasticsearch 中比较关键的基本概念有索引、文档、映射、映射类型、文档字段概念,为了方便理解,可以和关系数据库中的相关概念进行个比对:

技术图片

Elasticsearch 索引

  Elasticsearch 索引是映射类型的容器。一个 Elasticsearch 索引非常像关系型世界的数据库,是独立的大量文档集合。

  当然在底层,肯定用到了倒排索引,最基本的结构就是“keyword”和“PostingList”,Posting list就是一个 int的数组,存储了所有符合某个 term的文档 id。

  另外,这个倒排索引相比特定词项出现过的文档列表,会包含更多其它信息。

  它会保存每一个词项出现过的文档总数,在对应的文档中一个具体词项出现的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度等等相关信息。

文档 (Document)

  文档是 es 中所有可搜索数据的最小单位,比如日志文件中的日志项、一部电影的具体信息等等。

  文档会被序列化 JSON格式保存到 ElasticSearch ,JSON 对象由字段组成,每个字段都有对象的字段类型(字符串,数值,布尔,日期,二进制,范围类型)。

  同时每个文档都有一个 Unique ID,可以自己指定 ID,或者通过 ElasticSearch 自动生成

  所以严格来说,es 中存储的文档是一种半结构化的数据

映射

  映射(mapping)定义了每个字段的类型、字段所使用的分词器等。

  get /enjoy_test/_mapping

技术图片

可以显式映射,由我们在索引映射中进行预先定义;也可以动态映射,在添加文档的时候,由 es 自动添加到索引,这个过程不需要事先在索引进行字段数据类型匹配等等,es 会自己推断数据类型

既然说到了字段类型,当然就离不开字段的数据类型了。

文档字段

文档中的一个字段 field就相当于关系型数据库中的一列 column,那么它肯定有数据类型,es 提供的数据类型包括至少有

数据类型

核心数据类型

字符串类型:string,字符串类还可被分为 text和 keyword 类型,如果我们让 es自动映射数据,那么 es 会把字符串定义为 text,并且还加了一个 keyword类型字段。

text文本数据类型,用于索引全文值的字段。使用文本数据类型的字段,它们会被分词,在索引之前将字符串转换为单个术语的列表(倒排索引),分词过程允许 ES 搜索每个全文字段中的单个单词。什么情况适合使用 text,只要不具备唯一性的字符串一般都可以使用 text。

keyword,关键字数据类型,用于索引结构化内容的字段。使用 keyword 类型的字段,其不会被分析,给什么值就原封不动地按照这个值索引,所以关键字字段只能按其确切值进行搜索。什么情况下使用 keyword,具有唯一性的字符串,例如:电子邮件地址、MAC 地址、身份证号、状态代码...等等。

数字型数据类型:long、integer、short、byte、double、float

日期类型:date

布尔类型:boolean

复杂数据类型

数组:无需专门的数据类型

对象数据类型:单独的 JSON对象

嵌套数据类型:nested,关于 JSON对象的数组

地理数据类型

地理点数据类型

地理形状数据类型

专门数据类型

# IPv4 数据类型

单词计数数据类型 token_count

我们结合前面的映射来看看:

创建一个新的索引:put /open-soft

显式映射

put /open-soft/_mapping

{

"properties" : {

"corp" : {

"type" : "text"

},

"lang" : {

"type" : "text"

},

"name" : {

"type" : "text"

}

 

索引或者说入库个文档,注意这个文档的字段,比我们显示映射的字段要多个 star字段:

put /open-soft/_doc/1

{

"name": "Apache Hadoop",

"lang": "Java",

"corp": "Apache",

"stars":200

}

通过 get /open-soft/_mapping,我们可以看到 es 自动帮我们新增了 stars这个字段。

修改映射,增加一个新的字段:

put /open-soft/_mapping

{

"properties" : {

"year" : {

"type" : "integer"

}

}

}

数组

  不需要特殊配置,一个字段如果被配置为基本数据类型,就是天生支持数组类型的。任何字段都可以有 0个或多个值,但是在一个数组中数据类型必须一样。

比如:

put /open-soft/_doc/2

{

"name": ["Apache Activemq","Activemq Artemis"],

"lang": "Java",

"corp": "Apache",

"stars":[500,200]

}

是没问题的,但是如果:

put /open-soft/_doc/3

{

"name": ["Apache Kafka"],

"lang": "Java",

"corp": "Apache",

"stars":[500,"kafka"]

}

则会出错。

对象

JSON文档是有层次结构的,一个文档可能包含其他文档,如果一个文档包含其他文档,那么该文档值是对象类型,其数据类型是对象。当然 ElasticSearch中是没有所谓对象类型的,比如:

put /open-soft/_doc/object

{

"name": ["Apache ShardingSphere"],

"lang": "Java",

"corp": "JingDong",

"stars":400,

"address":{

"city":"BeiJing",

"country":"亦庄"

}

}

技术图片

对象类型可以在定义索引的映射关系时进行指定。

多数据类型

  如果说数组允许你使用同一个设置索引多项数据,那么多数据类型允许使用不同的设置,对同一项数据索引多次。带来的好处就是可以同一文本有多种不同的索引方式,比如一个字符串类型的字段,可以使用 text类型做全文检索,使用keyword 类型做聚合和排序。我们可以看到 es 的动态映射生成的字段类型里,往往字符串类型都使用了多数据类型。当然,我们一样也可以自己定义:

put /open-soft/_mapping

{

"properties" : {

"name" : {

"type" : "text",

"fields":{

"raw":{

"type" : "keyword"

},

"length":{

"type" : "token_count",

"analyzer":"standard"

}

}

}

}

}

  在上面的代码里,我们使用"fields"就把 name字段扩充为多字段类型,为name新增了两个子字段 raw和 length,raw设置类型为 keyword,length 设置类型为 token_count,告诉 es 这个字段在保存还需要做词频统计

  通过 fields字段设置的子字段 raw  length,在我们添加文档时,并不需要单独设置值,他们 name共享相同的值,只是 es 会以不同的方式处理字段值

  同样在检索文档的时候,它们也不会显示在结果中,所以它们一般都是在检索中以查询条件的形式出现,以减少检索时的性能开销。

字段参数 

 在上面的代码里出现了analyzer这个词,这是什么?这个叫字段参数,和 type一样,可以用来对字段进行配置。常用的字段参数和作用如下:

analyzer

  指定分词器。elasticsearch是一款支持全文检索的分布式存储系统,对于 text类型的字段,首先会使用分词器进行分词,然后将分词后的词根一个一个存储在倒排索引中,后续查询主要是针对词根的搜索。

analyzer该参数可以在每个查询、每个字段、每个索引中使用,其优先级如下(越靠前越优先):

  1、字段上定义的分词器

  2、索引配置中定义的分词器

  3、默认分词器(standard)

 

normalizer

  规范化,主要针对 keyword 类型,在索引该字段或查询字段之前,可以先对原始数据进行一些简单的处理,然后再将处理后的结果当成一个词根存入倒排索引中,默认为 null,比如:

PUT index

{

"settings": {

"analysis": {

"normalizer": {

"my_normalizer": { // 1

"type": "custom",

"char_filter": [],

"filter": ["lowercase", "asciifolding"] // 2

}

}

}

},

"mappings": {

"_doc": {

"properties": {

"foo": {

"type": "keyword",

"normalizer": "my_normalizer" // 3

}

}

}

}

}

代码 1:首先在 settings中的 analysis 属性中定义 normalizer。

代码 2:设置标准化过滤器,示例中的处理器为小写、asciifolding。

代码 3:在定义映射时,如果字段类型为 keyword,可以使用 normalizer

引用定义好的 normalizer

 

boost

权重值,可以提升在查询时的权重,对查询相关性有直接的影响,其默认值为1.0。其影响范围为词根查询(team query),对前缀、范围查询。5.0 版本后已废止

 

coerce

数据不总是我们想要的,由于在转换 JSON body 为真正 JSON 的时候,整型数字5有可能会被写成字符串"5"或者浮点数 5.0,这个参数可以将数值不合法的部分去除。默认为 true。

例如:将字符串会被强制转换为整数、浮点数被强制转换为整数。

例如存在如下字段类型:

"number_one": {

"type": "integer"

}

声明 number_one字段的类型为数字类型,那是否允许接收“6”字符串形式的数据呢?因为在 JSON中“6”用来赋给 int类型的字段,也是能接受的,默认 coerce  true,表示允许这种赋值,但如果 coerce 设置为 false,此时 es只能接受不带双引号的数字,如果在 coerce=false ,将“6”赋值给 number_one时会抛出类型不匹配异常。

 

copy_to

copy_to参数允许您创建自定义的_all字段。换句话说,多个字段的值可以复制到一个字段中。

例如,first_name和 last_name 字段可以复制到 full_name 字段如下:

PUT my_index

{

"mappings": {

"_doc": {

"properties": {

"first_name": {

"type": "text",

"copy_to": "full_name"

},

"last_name": {

"type": "text",

"copy_to": "full_name"

 

表示字段 full_name的值来自 first_name + last_name。

关于 copy_to重点说明:

1、字段的复制是原始值。

2、同一个字段可以复制到多个字段,写法如下“copy_to”: [ “field_1”,

“field_2”]

doc_values

  Doc values 的存在是因为倒排索引只对某些操作是高效的。倒排索引的优势在于查找包含某个项的文档,而对于从另外一个方向的相反操作并不高效,即:确定哪些项是否存在单个文档里,聚合需要这种次级的访问模式。

  对于以下倒排索引:

技术图片

  如果我们想要获得所有包含 档的词的完整列表,倒排索引是根据项来排序的,所以我们首先在词 ,然后扫描所有列,找到包含 brown 的文档。我们可以快速 和 包含 brown 这个 token。

  然后,对于聚合部分,我们需要找到 Doc_1  Doc_2 里所有唯一的词项。用倒排索引做这件事情代价很高:我们会迭代索引里的每个词项并收集 Doc_1  Doc_2 列里面 token。这很慢而且难以扩展:随着词项和文档的数量增加,执行时间也会增加。

  Doc values 通过转置两者间的关系来解决这个问题。倒排索引将词项映射到包含它们的文档,doc values 将文档映射到它们包含的词项

技术图片

当数据被转置之后,想要收集到 Doc_1  Doc_2 的唯一 token 会非常容易。获得每个文档行,获取所有的词项,然后求两个集合的并集。

doc_values缺省是 true,即是开启的,并且只适用于非 text类型的字段。

dynamic

  是否允许动态的隐式增加字段。在执行 index api 或更新文档 API ,对于_source字段中包含一些原先未定义的字段采取的措施,根据 dynamic 的取值,会进行不同的操作:

  true,默认值,表示新的字段会加入到类型映射中。

  false,新的字段会被忽略,即不会存入_souce字段中,即不会存储新字段,也无法通过新字段进行查询。

  strict,会显示抛出异常,需要新使用 put mapping api 先显示增加字段映射

enabled

  是否建立索引,默认情况下为 true,es 会尝试为你索引所有的字段,但有时候某些类型的字段,无需建立索引,只是用来存储数据即可。也就是说,

ELasticseaech默认会索引所有的字段,enabled设为 false的字段,elasicsearch 会跳过字段内容,该字段只能从_source 中获取,但是不可搜。只有映射类型(type)和object 类型的字段可以设置 enabled属性。

eager_global_ordinals

  表示是否提前加载全局顺序号。Global ordinals 一个建立在 doc values fielddata基础上的数据结构, 它为每一个精确词按照字母顺序维护递增的编号每一个精确词都有一个独一无二的编号 并且 精确词 A 小于精确词 B 的编号.Global ordinals 只支持 keyword  text 型字段,在 keyword 字段中默认是启用的 而在 text 型字段中 只有 fielddata 和相关属性开启的状态下才是可用的

fielddata

  为了解决排序与聚合,elasticsearch 提供了 doc_values 属性来支持列式存储,但doc_values 不支持 text 字段类型。因为 text 字段是需要先分析(分词),会影响 doc_values 列式存储的性能

  es 为了支持 text字段高效排序与聚合,引入了一种新的数据结构(fielddata),使用内存进行存储。默认构建时机为第一次聚合查询、排序操作时构建,主要存储倒排索引中的词根与文档的映射关系,聚合,排序操作在内存中执行。因此fielddata需要消耗大量的 JVM 堆内存。一旦 fielddata加载到内存后,它将永久存在。

  通常情况下,加载 fielddata 一个昂贵的操作,故默认情况下,text 字段的字段默认是不开启 fielddata机制。在使用 fielddata 之前请慎重考虑为什么要开启fielddata。

format

  在 JSON文档中,日期表示为字符串。Elasticsearch 使用一组预先配置的格式来识别和解析这些字符串,并将其解析为 long类型的数值(毫秒),支持自定义格式,也有内置格式。

比如:

 

PUT my_index

{

"mappings": {

"_doc": {

"properties": {

"date": {

"type": "date",

"format": "yyyy-MM-dd HH:mm:ss"

}}}}}

elasticsearch为我们内置了大量的格式,如下:

epoch_millis

时间戳,单位,毫秒,范围受限于 Java Long.MIN_VALUE和 Long.MAX_VALUE。

epoch_second

时间戳,单位,秒,范围受限于 Java的限制 Long.MIN_VALUE  Long.

MAX_VALUE 除以 1000(一秒中的毫秒数)。

date_optional_time或者 strict_date_optional_time

日期必填,时间可选,其支持的格式如下:

date-opt-time = date-element [‘T‘ [time-element] [offset]]

date-element = std-date-element | ord-date-element | week-date-element

std-date-element = yyyy [‘-‘ MM [‘-‘ dd]]

ord-date-element = yyyy [‘-‘ DDD]

week-date-element = xxxx ‘-W‘ ww [‘-‘ e]

time-element = HH [minute-element] | [fraction]

minute-element = ‘:‘ mm [second-element] | [fraction]

second-element = ‘:‘ ss [fraction]

比如"yyyy-MM-dd"、"yyyyMMdd"、"yyyyMMddHHmmss"、

"yyyy-MM-ddTHH:mm:ss"、"yyyy-MM-ddTHH:mm:ss.SSS"、

"yyyy-MM-ddTHH:mm:ss.SSSZ"格式,不支持常用的"yyyy-MM-dd HH:mm:ss"等格式。

 

注意,"T"和"Z"是固定的字符。

tips:如果看到“strict_”前缀的日期格式要求,表示 date_optional_time 的严格级别,这个严格指的是年份、月份、天必须分别以 4位、2 、2 位表示,不足两位的话第一位需用 0补齐。

   basic_date

其格式表达式为 yyyyMMdd

basic_date_time

其格式表达式为yyyyMMddTHHmmss.SSSZ

basic_date_time_no_millis

其格式表达式为yyyyMMddTHHmmssZ

basic_ordinal_date

4位数的年 + 3 (day of year)其格式字符串为 yyyyDDD

basic_ordinal_date_time

其格式字符串为 yyyyDDDTHHmmss.SSSZ

basic_ordinal_date_time_no_millis

其格式字符串为 yyyyDDDTHHmmssZ

basic_time

其格式字符串为 HHmmss.SSSZ

basic_time_no_millis

其格式字符串为 HHmmssZ

basic_t_time

其格式字符串为THHmmss.SSSZ

basic_t_time_no_millis

其格式字符串为THHmmssZ

basic_week_date

其格式字符串为 xxxxWwwe4 为年 然后用W, 2  week of year(所在年里周序号)1 day of week技术图片技术图片技术图片技术图片技术图片

basic_week_date_time

其格式字符串为 xxxxWwweTHH:mm:ss.SSSZ.

basic_week_date_time_no_millis

其格式字符串为 xxxxWwweTHH:mm:ssZ.

date

其格式字符串为 yyyy-MM-dd

date_hour

其格式字符串为 yyyy-MM-ddTHH

date_hour_minute

其格式字符串为 yyyy-MM-ddTHH:mm

date_hour_minute_second

其格式字符串为 yyyy-MM-ddTHH:mm:ss

date_hour_minute_second_fraction

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_hour_minute_second_millis

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_time

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_time_no_millis

其格式字符串为 yyyy-MM-ddTHH:mm:ss

hour

其格式字符串为 HH

hour_minute

其格式字符串为 HH:mm

hour_minute_second

其格式字符串为 HH:mm:ss

hour_minute_second_fraction

其格式字符串为 HH:mm:ss.SSS

hour_minute_second_millis

其格式字符串为 HH:mm:ss.SSS

ordinal_date

其格式字符串为 yyyy-DDD,其中 DDD day of year

ordinal_date_time

其格式字符串为 yyyy-DDDTHH:mm:ss.SSSZZ,其中 DDD day of year

ordinal_date_time_no_millis技术图片技术图片技术图片技术图片技术图片技术图片技术图片

其格式字符串为 yyyy-DDDTHH:mm:ssZZ

time

其格式字符串为 HH:mm:ss.SSSZZ

time_no_millis

其格式字符串为 HH:mm:ssZZ

t_time

其格式字符串为THH:mm:ss.SSSZZ

t_time_no_millis

其格式字符串为THH:mm:ssZZ

week_date

其格式字符串为 xxxx-‘Www-e,4 位年份ww 表示 week of yeare 表示 dayof week

week_date_time

其格式字符串为 xxxx-‘Www-eTHH:mm:ss.SSSZZ

week_date_time_no_millis

其格式字符串为 xxxx-‘Www-eTHH:mm:ssZZ

weekyear

其格式字符串为 xxxx

weekyear_week

其格式字符串为 xxxx-‘Www,其中 ww  week of year

weekyear_week_day

其格式字符串为 xxxx-‘Www-e,其中 ww  week of year,e day of week

year

  其格式字符串为 yyyy

  year_month

  其格式字符串为 yyyy-MM

year_month_day

  其格式字符串为 yyyy-MM-dd

ignore_above

ignore_above用于指定字段索引和存储的长度最大值超过最大值的会被忽略。

ignore_malformed

 

 ignore_malformed可以忽略不规则数据对于 login 字段有人可能填写的是date类型也有人填写的是邮件格式个字段索引不合适的数据类型发生异常导致整个文档索引失败如果 ignore_malformed参数设为 true异常会被忽

出异常的字段不会被索引其它字段正常索引

 




技术图片

 

basic_date

其格式表达式为 yyyyMMdd

basic_date_time

其格式表达式为yyyyMMddTHHmmss.SSSZ

basic_date_time_no_millis

其格式表达式为yyyyMMddTHHmmssZ

basic_ordinal_date

4位数的年 + 3 (day of year)其格式字符串为 yyyyDDD

basic_ordinal_date_time

其格式字符串为 yyyyDDDTHHmmss.SSSZ

basic_ordinal_date_time_no_millis

其格式字符串为 yyyyDDDTHHmmssZ

basic_time

其格式字符串为 HHmmss.SSSZ

basic_time_no_millis

其格式字符串为 HHmmssZ

basic_t_time

其格式字符串为THHmmss.SSSZ

basic_t_time_no_millis

其格式字符串为THHmmssZ

basic_week_date


 

 

 

 

 

 

 

 

其格式字符串为 xxxxWwwe4 为年 然后用W, 2  week of year(所在年里周序号)1 day of week技术图片技术图片技术图片技术图片技术图片

basic_week_date_time

其格式字符串为 xxxxWwweTHH:mm:ss.SSSZ.

basic_week_date_time_no_millis

其格式字符串为 xxxxWwweTHH:mm:ssZ.

date

其格式字符串为 yyyy-MM-dd

date_hour

其格式字符串为 yyyy-MM-ddTHH

date_hour_minute

其格式字符串为 yyyy-MM-ddTHH:mm

date_hour_minute_second

其格式字符串为 yyyy-MM-ddTHH:mm:ss

date_hour_minute_second_fraction

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_hour_minute_second_millis

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_time

其格式字符串为 yyyy-MM-ddTHH:mm:ss.SSS

date_time_no_millis

其格式字符串为 yyyy-MM-ddTHH:mm:ss

hour

其格式字符串为 HH

hour_minute

其格式字符串为 HH:mm

hour_minute_second

其格式字符串为 HH:mm:ss

hour_minute_second_fraction

其格式字符串为 HH:mm:ss.SSS

hour_minute_second_millis

其格式字符串为 HH:mm:ss.SSS

ordinal_date

其格式字符串为 yyyy-DDD,其中 DDD day of year

ordinal_date_time

其格式字符串为 yyyy-DDDTHH:mm:ss.SSSZZ,其中 DDD day of year


 

 

 

 

 

 

 

 

ordinal_date_time_no_millis技术图片技术图片技术图片技术图片技术图片技术图片技术图片

其格式字符串为 yyyy-DDDTHH:mm:ssZZ

time

其格式字符串为 HH:mm:ss.SSSZZ

time_no_millis

其格式字符串为 HH:mm:ssZZ

t_time

其格式字符串为THH:mm:ss.SSSZZ

t_time_no_millis

其格式字符串为THH:mm:ssZZ

week_date

其格式字符串为 xxxx-‘Www-e,4 位年份ww 表示 week of yeare 表示 dayof week

week_date_time

其格式字符串为 xxxx-‘Www-eTHH:mm:ss.SSSZZ

week_date_time_no_millis

其格式字符串为 xxxx-‘Www-eTHH:mm:ssZZ

weekyear

其格式字符串为 xxxx

weekyear_week

其格式字符串为 xxxx-‘Www,其中 ww  week of year

weekyear_week_day

其格式字符串为 xxxx-‘Www-e,其中 ww  week of year,e day of week

year

 

 

 

 

 

 

year_month_day

其格式字符串为 yyyy-MM-dd

ELK入门及基本使用

标签:永久   cti   amp   概念   查询条件   sel   null   还需要   linu   

原文地址:https://www.cnblogs.com/Soy-technology/p/13109395.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!