ElasticSearch 技术分析与实战 读后感

《第一章:ElasticSearch》

ES简介

ElasticSearch 是一个实时的分布式搜索和分析引擎,是一个基于Lucence 构建的开源,分布式,restful接口全文搜索引擎。ES 还是一个分布式,文档型的数据库,其中每个字段均是被索引的数据且可被搜索,它能够扩展到数以百计的服务器存储以及处理PB级别的数据。可以在很短的时间内存储,搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的首选。ES 就是为高可用和可扩展而生的,通过购置性能更强的服务器来完成,称为垂直扩展或向上扩展,增加增多的服务器来完成,称为水平扩展或者向外扩展。实际生产中更多的是来自水平扩展,通过向集群中添加更多的节点来分担负载,增加可靠性。

它提供了一个分布式多用户能力的全文搜索引擎,基于restful web 接口,ElasticSearch 是用java 开发的,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

Logstash:

Logstash:Logstash 是一款轻量级的日志搜集处理框架,可以方便的把分散的,多样化的日志搜集起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件。

dos 命令进入:cd C:\tools\Logstash\logstash-5.6.8\bin
    输入: logstash -e "input{ stdin{}} output{stdout{}}"

命令行解释:
stdin 表示输入流,指从键盘输入
stdout 表示输出流,指从显示器输出
-e 执行
--config 或-f 配置文件,后跟参数类型可以是一个字符串的配置或全路径文件名或全路径。

使用场景

1.搜索商品[使用ES 存储整个产品目录和库存信息,为客户提供精准搜索和推荐]
2.搜集日志或者交易数据,分析和挖掘数据,进行统计,总结。
3.京东的设置购买价格通知,定时同步供应商的价格到ES,使用定时器来匹配客户的需求,当查询价格低于客户设定的值后推送消息。
4.当有千万条数据记录时,商品智能分析的需求,快速调查,分析和可视化,可以使用ES 来存储数据,然后用Kibanna 建立自定义仪表板。使用ES的聚合功能来执行复杂的商品报表和数据查询。
5.数据分析,排名,推荐。
适用程序1.数据量较大,es的分布式本质,可以帮助你快速进行扩容,承载大量数据。
2.数据结构灵活多变,随时可能变化,而且数据结构之间的关系,非常复杂。
3.对数据的相关操作,非常方便。
特点:1.可以做为一个大型分布式集群(数百台服务器)技术,处理PB级数据,服务大公司;也可以运行在单机上。
2.将全文检索,数据分析以及分布式技术,合并在一起,才形成了独一无二的ES。
3.开箱即用,部署简单。
4.全文检索,同义词处理,相关度排名,复杂数据分析,海量数据的近实时处理。
ES 的优点1.横向可扩展性:只需要增加一台服务器,做一点儿配置,启动一下ES进程就可以并入集群。
2.分片机制提供更好的分布性:同一个索引分成多个分片(sharding),这点类似于HDFS 的块机制,分而治之的方式可以提升处理效率。
3.高可用:提供复制(replica)机制,一个分片可以设置多个复制,使得某台服务器在宕机的情况下,集群仍旧可以照常运行,并且会把服务器宕机丢失的数据信息复制恢复到其他可用节点上
4.使用简单:只需要一条命令就可以下载文件,然后很快就能搭建一个站内搜索引擎。
5.自动维护数据的分布到多个节点的索引的建立,还有搜索请求分布到多个节点的执行
6.封装了更多的高级功能,给我们提供更多高级的支持,让我们快速开发应用,开发更加复杂的应用,复杂的搜索功能,聚合分析的功能。
7.基于地理位置的搜索。
8.对海量数据进行实时的处理。因为ES是分布式的,ES 自动可以将海量数据分散到多台服务器上去存储和检索。
相关产品Beats :它是一个代理,将不同类型的数据发送到Elasticsearch中。它可以直接将数据 发送到 Elasticsearcho Beats 由三部分内容组成:Filebeat、Topbeat、Packetbeatc Filebeat 用 来收集日志。Topbeat用来收集系统基础设置数据,如CPU、内存、每个进程的统计信息。 Packetbeat是一个网络包分析工具,统计收集网络信息。这三个工具是官方提供的。
Shield :它为Elasticsearch带来企业级的安全性,加密通信,认证保护整个Elasticsearch 数据,它是基于角色的访问控制与审计。当今企业对安全需求越来越重视,Shield可以提 供安全的Elasticsearch访问,从而保护核心的数据。注意:Shield是收费的产品。
Watcher:它是Elasticsearch的警报和通知工具:它可以主动监测Elasticsearch的状态, 并在有异常的时候进行提醒,还可以根据你的数据变化情况来采取不同的处理方式。注意: Watcher也是收费的产品。
Marvel :它是Elasticsearch的管理和监控工具。它监测Elasticsearch集群索引和节点的 活动,快速诊断问题。注意:Marvel也是收费的产品。
ElasticSearch 和mysql 数据库逻辑结构概念对比:
ElasticSearch关系型数据库mysql
索引 index数据库 databases
类型 table表 table
文档 document行 row
ES检索分为3种:全文检索 / 结构化检索  / 数据分析
全文搜索

全文搜索是指计算机搜索程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,搜索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户。

全文搜索:select * from product where productName like '%xxx%'

结构化检索[搜索某一类下有哪些商品]:select * from product where category_id = '';

Lucene

倒排索引概念

倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因此称为倒排索引inverted index。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件。


倒排索引的索引对象是文档或者文档集合中的单词,用来存储这些单词在一个文档或者一组文档中的存储位置,是对文档或者文档集合的一种最常用的索引机制。

数据分析:我们分析每一个商品分类下有多少个商品: select count(*) from product group by category_id;

LK分词

LK分词是一款国人开发的相对简单的中文分词器,默认的中文分词是将每个字分成一个词,在实际应用中,不符合逻辑,需要安装中词分词器来解决这个问题。

IK提供了两个分词算法LKSmart 和 LKMaxWord,其中LKSmart为最少切分,LKMaxWord为最细粒度划分

将elasticsearch 支持中文分词如下:

1.下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

2.解压后重新命名文件夹lk,并将其拷贝到elasticsearch 工具的bin 目录下

3.支持自定义中文词,进入C:\tools\elasticsearch\elasticsearch-5.6.8\bin\lk\config,新建一个my.dic配置文件:眸光流转,仿若花开

搜索步骤

搜索引擎的关键步骤就是建立倒排索引,倒排索引一般表示为一个关键词然后是它的频率(出现的次数)、位置(出现在哪一篇文章或网页中,及有关的日期,作者等信息),好 比一本书的目录、标签一般读者想看哪一个主题相关的章节,直接根据目录即可找到相关 的页面。不必再从书的第一页到最后一页,一页一页地查找。

1.取得关键词:由于Lucene是基于关键词索引和查询的,首先我们要取得文章的关键词:

    1-1.文章内容,即一个字符串,先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间由于是连在一起的,所以需要特殊的分词处理。

    1-2.文章中的“ in” “once” “too”等词没有什么实际意义,中文中的“的” “是”等字通 常也无具体含义,这些不代表概念的词是可以过滤掉的。

    1-3.用户通常希望查“He”时能把含“he”和“HE”的文章也找出来,所以所有单词 需要统一大小写。

    1-4.用户通常希望查“live”时能把含“lives”和“lived”的文章也找出来,所以需要 把“lives”, *'lived"还原成“live”。

    1-5.文章中的标点符号通常不表示某种概念,也可以过滤掉。
 

2.建立倒排索引:有了关键词后,开始建立倒排索引。通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现的次数和位置,通常有两种位置:
   
2-1.字符位置,即记录该词是文章中第几个字符(优点是显示并定位关键词快)。
   2-2.关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组查询 快),Lucene中记录的就是这种位置。
   2-3.关键字是按字符顺序排列的(Lucene没有使用B树结构),因此Lucene可以用二元搜索算法快速定位关键词。

3.实现:实现时,Lucene将关键词,出现频率,出现位置分别作为词典文件(Term Dictionary),频率文件(frequencies)、 位置文件(positions)保存。其中词典文件不仅保存了每个关键词,还保留了指向频率文件和 位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息.


Lucene中使用了 field的概念,用于表达信息所在位置(如标题中、文章中、URL中), 在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息,因为每个 关键字一定属于一个或多个held。
 

4.为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为 < 前缀长度,后缀〉,例如: 当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语〉。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减少数字的 长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389 (不压缩要用3个字 节保存),上一文章号是16382,压缩后保存7 (只用一个字节)。

总结:

1.在Lucene中以上措施由Analyzer类完成。

2.下面我们可以通过对该索引的查询来解释一下为什么要建立索引:
假设要查询单词“live”,Lucene先对词典二元查找、找到该词,通过指向频率文件 的指针读出所有文章号,然后返回结果匚词典通常非常小,因而,整个过程的时间是毫秒 级的.

Lucene 简介Lucene 是Apache 软件基金会中一个开源代码的全文搜索引擎工具包,是一个全文搜索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文搜索的功能,或者是以此为基础建立起完整的全文搜索引擎。

ElasticSearch术语及概念:

索引词:term,ElasticSearch索引词term 是一个能够被索引的精确值,foo,Foo,FOO 几个词是不同的索引词,索引词term 是可以通过term 查询进行准确的查找。
文本:text,文本是一段普通的非结构化文字,文本会被分析成一个个的索引词,存储在ES的索引库中。为了能够让文本能够进行搜索,文本字段需要事先进行分析;当对文本中的关键词进行查询的时候,搜索引擎应该根据搜索条件搜索出原文本。
分析:analysis,分析是将文本转换为索引词的过程,分析的结果依赖于分词器。
集群:

cluster,集群由一个或多个节点组成,对外提供服务,对外提供索引和搜索功能。在所有节点,一个集群有一个唯一的名称默认为"Elasticsearch"。此名称很重要,因为每个节点只能是集群的一部分,当该节点被设置为相同的集群名称时,就会自动加入集群当需要有多个集群的时候,要确保每个集群的名称不能重复,否则,节点可能会加入错误的集群。

你可以拥有多个独立的集群,每个集群都有不同的集群名称。

注意:一个节点只能加入一个集群。

节点 :

node,一个节点时一个逻辑上独立的服务,它是集群的一部分,可以存储数据,并参与集群的索引和搜索功能。节点也有名称且唯一,默认是随机分配的在启动的时候分配。如果不想要默认名称,可以自定义节点名。

节点名字在管理中很重要,在网络中,ElasticSearch 集群通过节点名称进行管理和通信。一个节点可以被配置加入一个特定的集群。

默认情况下,每个节点会加入名为ElasticSearch集群中,这意味着如果在网络上启动多个节点,如果网络畅通,他们能够发现并自动加入一个名为ElasticSearch的集群中。

在一个集群中,你可以拥有多个节点,当网络没有集群运行的时候,只要启动任何一个节点,这个节点会默认生成一个新的集群,这个集群会有一个节点。

路由:routing,当存储一个文档的时候,它会存储在唯一的主分片中,具体哪个分片是通过散列值进行选择。默认情况下,这个值是由文档的ID生成,如果文档有一个指定的父级文档,则从父级文档ID中生成,该值可以在存储文档的时候进行修改。
分片shard:

分片是单个Lucene实例,这是ElasticSearch管理的比较底层的功能索引是指向主分片和副本分片的逻辑空间。对于使用,只需要指定分片的数量。在开发过程中,我们对应的对象都是索引,ElasticSearch会自动管理集群中的所有的分片,当发生故障,ElasticSearch会把分片移动到不同的节点或者添加新的节点。

index 会被拆分为多个shard,每个shard 就会存放这个index 的一部分数据,这些shard 会散落在多台服务器上面。

一个索引可以存储很大的数据,这些空间可以超过一个节点的物理存储的限制。举例:十亿个文档占用磁盘空间为1TB,仅仅从单个节点搜索可能会很慢,还有一台物理机器也不一定能存储这么多的数据,为了解决这一问题,ElasticSearch 将索引分解成多个分片。当你创建一个索引,你可以简单的定义你想要的分片数量。每个分片本身是一个全功能的,独立的单元,可以托管在集群中的任何节点。

主分片

primary shard:每个文档都存储在一个分片中,当你存储一个文档的时候,系统会首先存储在主分片中,然后会复制到不同的副本中,默认情况下,一个索引有5个主分片。你可以实现指定分片的数量,当分片一旦建立,则不能修改。

注意:shard 优点: 横向扩展,比如数据量很多,重新建立一个shard的索引,将数据导入进入。数据分布在多个shard,多台服务器上,所有的操作都会在多台服务器上并行分布式执行,提高吞吐量和性能。

副本分片

 replica shard,每一个分片有零个或多个副本,副本主要是主分片的复制,有两个目的:

 1. 增加高可用:当节点失败的时候不受影响。当主分片失败的时候,可以从副本分片中选择一个作为主分片。【一个复制的分片不会存储在同一个节点中】

 2.提高性能:当查询的时候可以到主分片或副本分片中进行查询。默认情况下,一个主分片配有一个副本,但副本的数量可以在后面动态的配置添加。副本分片必须部署在不同的节点上,不能部署在和主分片相同的节点上。

分片主要有两个很重要的原因:

1.允许水平分割扩展数据

2.允许分配和并行操作,从而提高性能和吞吐量。

复制分片

replica,replica shard的简称。每一个分片有0 或多个副本。副本主要是主分片的复制,复制时一个重要的功能,不然会有单点问题。当网络中的某个节点出现问题时,复制可以对故障进行转移,保证系统的高可用。所以,ES 允许你创建一个或多个拷贝,你的索引分片就形成了所谓的副本/副本分片。有两个目的:
 

1. 增加高可用:当节点失败的时候不受影响。当主分片失败的时候,可以从副本分片中选择一个作为主分片。注意:一个复制的分片不会存储在同一个节点中。

2.它允许你扩展搜索量,提高并发量,因为搜索可以在所有副本上并行执行。

3.提高性能:当查询的时候可以到主分片或副本分片中进行查询。默认情况下,一个主分片配有一个副本,但副本的数量可以在后面动态的配置添加。副本分片必须部署在不同的节点上,不能部署在和主分片相同的节点上

每个索引可以拆分成多个分片,索引可以复制零个或多个分片,一旦复制,每个索引就有了主分片和副本分片。分片的数量和副本的数量可以在创建索引时定义。当创建索引后,你可以随便改变副本的数量,但你不能改变分片的数量。

默认情况下,每个索引分配5个分片和一个副本,这意味着你的集群节点至少要有两个节点,你将拥有5个主要的分片和5个副本分共10个分片。

总结

分片主要有两个很重要的原因:

1.允许水平分割扩展数据。
2.允许分配和并行操作,从而提高性能和吞吐量。

默认情况下,每个索引分配5个分片和一个副本,这意味着你的集群至少需要有2个节点,拥有5个主要的分片和5个副本分片一共10个分片。

索引:

index,包含一堆有相似结构的文档数据,一个index 就代表了一类类似的或者相同的document。

注意:索引名称必须小写,不能用下划线开头,不能包含逗号。

类型:

type,每个索引都可以由一个或多个type,type 是index中的一个逻辑分区(数据分类),一个type下的document ,都有相同的field,或许会有轻微的field 不同。

注意:type 名称可以是大写或者小写,但不能用下划线开头,不能包含逗号。

文档 :

document,文档时存储在ElasticSearch中的一个json格式的字符串。类似在关系数据库中的一行数据记录。每个存储在索引中的一个文档都有一个类型和一个id,每个文档都是一个json对象,存储了0个或多个字段,或者键值对。原始的json文档被存储在一个叫做_source的字段中。当搜索文档的时候默认返回的就是这个字段。

ElasticSearch中的最小数据单元,一个document 可以是一条客户数据,一条商品分类数据,通常用JSON 数据结构表示,每个index 下的type 中,都可以存储多个document。一个document 里面有多个field,每个field 就是一个数据字段。原始的JSON 文档被存储在一个叫做_source 的字段中,当搜索文档的时候默认返回的就是这个字段。

映射:mapping,映射像关系数据库中的表结构,每一个索引都有一个映射,它对应了索引中的每一个字段类型,以及一个索引范围内的设置,一个映射可以事先被定义,或者在第一次存储文档的时候自动识别。
字段field:文档中包含零或多个字段,字段可以是一个简单的值(字符串,整数,日期),也可以是一个数组或对象的嵌套结构,字段类似与关系数据库中表的列。每个字段都对应一个字段类型,例如整数,字符串,对象等。字段还可以指定如何分析该字段的值。

来源

字段

source field,默认情况下,你的原文档被存储在_source 这个字段中,当你查询的时候也是返回这个字段。这允许你可以从搜索结果中访问原始的对象,这个对象返回一个精准的JSON字符串,这个对象不显示索引分析后的其他任何数据。

主键ID

ID 是一个文件的唯一标识,如果在存库的时候没有提供ID,系统会自动生成一个ID,文档的index/tepe/id 必须是唯一的。

0._id 元数据:
1.代表document 的唯一标识,与index 和 type 一起,可以唯一标识和定位一个document。我们可以手动的指定id,也可以不指定,由ES 自动为我们创建一个id。

id 的生成使用场景:

如果是从数据库导入,就使用手动指定,如果数据存储直接就放es,那么就用自动生成id。

1. 手动生成id method:
PUT /test_index/test_type/2
{
 "test_content":"my test"
}
2. 自动生成id method:
POST /test_index/test_type
{
 "test_content":"my test"
}

注意: 自动生成的id,长度为20个字符,URL 安全,base64编码,GUID算法生成,GUID 算法,可以保证,分布式环境下,不同节点同一时间创建的id 一定不冲突。

JSON

JSON,在 elasticSearch 的接口中,大多数都是以JSON的进行的。JSON 是一种轻量级的数据交换格式,易于人们阅读和编写,同时也易于机器解析和生成。

JSON有两种结构:

1."key/value”键值对的集合。如对象(object)、记(record)结构(struct)字典(dictionary)哈希表(hash table).有键列表(keyed list)或者关联数组(associative array)。

2.值的有序列表(An ordered list of values)在大部分语言中,是指数组(array) 。 当需要表示一组值时,JSON不但能够提高可读性,而且可以减少复杂性。 

json 采用完全独立于语言的文本格式。可读性更好,减少复杂性。json时完全动态的,允许在json结构的中间改变表示数据的方式。在处理json格式的数据时,没有需要遵守的预定义约束。所以在同样的数据结构中,可以改变表示数据的方式,甚至可以用不同方式表示同一事物

近实时near realtime:从写入到读取大概1秒延迟。基于ES执行搜索和分析可以达到秒级。
JSON 有两种结构

1.名称/值 对的集合 :对象,记录,结构,字典,哈希表,有键列表,关联数据。

2.值的有序列表: 数组。

安装ElasticSearch:

前置条件

windows 10 安装nodeJS: https://www.cnblogs.com/zhouyu2017/p/6485265.html

windows 10 :启动es报错解决方案
https://blog.csdn.net/laotoumo/article/details/53890279

下载地址

https://www.elastic.co/cn/downloads/past-releases#elasticsearch

解压进入:C:\tools\elasticsearch\elasticsearch-5.6.8\bin
执行:elasticsearch.bat
启动成功

页面访问:http://127.0.0.1:9200  显示如下即代表成功:

{
  "name" : "40QKEaJ",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "zevBWuSmRjuyRB4MILrdsw",
  "version" : {
    "number" : "5.6.8",
    "build_hash" : "688ecce",
    "build_date" : "2018-02-16T16:46:30.010Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}
head 插件的安装:如果都是通过rest 请求的方式使用ElasticSearch不方便,head  提供了图形化界面实现elasticsearch 的日常管理。
下载地址:

 Past Releases of Elastic Stack Software | Elastic

1.下载head 插件:https://github.com/mobz/elasticsearch-head
2.解压到指定目录
3.安装node.js [引导地址]:

 nodeJs 安装及使用_welcome to 一点点 home-CSDN博客

4.配置node.js 环境变量:
5.安装cnpm: npm install -g cnpm -registry=https://registry.npm.taobao.org
6.npm install -g grunt-cli
7.安装依赖: cnpm install
8.进入head 目录启动head,在命令提示符下输入命令:

cd C:\tools\es-head\elasticsearch-head-master

npm run start

访问地址:http://127.0.0.1:9100/

进入C:\tools\elasticsearch\elasticsearch-5.6.8\config 修改elasticsearch.yml [最下方增加两行代码]:

# 增加如下字段
http.cors.enabled: true
http.cors.allow-origin: "*"

重新启动ES
总结:

ElasticSearch 是Java 开发的,所以JVM 的环境变量 JAVA_OPTS 对ElasticSearch 是重要的,在JAVA_OPTS 中对ElasticSearch 最重要的参数是-Xmx 最大可以使用内存的参数,一般情况下内存更能发挥ElasticSearch 作用。建议 -Xmx 设置为物理内存的一半,为了减少内存分配带来的性能损耗,最好一开始就设置初始内存和最大内存都为物理内存的一半,即Xms 和 Xmx 这两个参数。

由于JAVA_OPTS 大多数时候对整个机器环境起作用,所以最好是保留默认的java_opts ,最好用 ES_JAVA_OPTS 环境变量设置来作为java_opts 参数。

默认配置文件在ElasticSearch/bin/ElasticSearch.in.sh中:

if [ "x$ES_MIN_MEM" = "x" ]; then
    ES_MIN_MEM=256m
fi
if [ "x$ES_MAX_MEM" = "x" ]; then
    ES_MAX_MEM=1g
fi
if [ "x$ES_HEAP_SIZE" != "x" ]; then
    ES_MIN_MEM=$ES_HEAP_SIZE
    ES_MAX_MEM=$ES_HEAP_SIZE
fi

# min and max heap sizes should be set to the same value to avoid
# stop-the-world GC pauses during resize, and so that we can lock the
# heap in memory on startup to prevent any of it from being swapped
# out.
JAVA_OPTS="$JAVA_OPTS -Xms${ES_MIN_MEM}"
JAVA_OPTS="$JAVA_OPTS -Xmx${ES_MAX_MEM}"

配置

ElasticSearch配置文件在 elasticSearch/config 文件夹下:两个配置文件,一个是elasticSearch 配置不同模块的配置文件elasticSearch.yml ,另一个是elasticSearch 日志配置文件logging.yml 文件,默认配置文件的格式为yml。

elasticSearch 提供给了多种方式进行配置,在系统内部,都使用命名空间来标识这些设置,根据这些命名空间,系统可以很容易的扩展到其他格式。

ElasticSearch.yml 配置说明:

集群名称:cluster.name: dev-application
确保在不同的环境中集群的名称不重复,否则,节点可能会连接到错误的集群上。


节点名称:node.name: node-1
默认情况下,当节点启动时ElasticSearch 将随机在一份3000个名字的列表中随机指定一个。如果机器上只运行一个集群ElasticSearch 节点,可以用${HOSTNAME} 设置节点的名称为主机名。

配置说明

节点描述: node.rack: r1

索引存储位置: path.data: /path/to/data

日志存储位置: path.logs: /path/to/logs

内存分配模式: bootstrap.mlockall: true

绑定的网卡IP: network.host: 192.168.0.1

http 协议端口:http.port:9200

开始发现新节点的IP地址: discovery.zen.ping.unicast.hosts:{"host1","host2"}

最多发现主节点的个数:discovery.zen.mininum_master_nodes: 3

当重启集群节点后最少启动N个节点后开始做恢复: gateway.recover_after_nodes: 3

当一台机器上最多启动的节点数: node.max_local_storage_nodes: 1

当删除一个索引的时候,需要指定具体索引的名称: action.destrucive_requires_name: true

索引配置说明: 在集群中创建的索引可以提供每个索引自己的设置。
创建一个索引刷新间隔为5秒而不是默认的刷新间隔,这个索引参数可以设置在节点上,比如elasticsearch.yml 文件:

index.refresh_interval: 5s

在启动ElaticSearch 的时候用参数指定也可以:

elasticsearch -Des.index.refresh_interval = 5s

日志

配置

ElaticSearch 内部使用log4j 记录系统日志,使用yml 格式,在config/logging.yml 中配置。JSON 格式和键值对的格式也支持。

可以加载多个配置文件,在启用ElaticSearch 后系统自动合并多个配置文件,支持不同的后缀格式: .yml  .yaml  .json   .properties

记录器部分包含Java 包和相应的日志级别,在配置中可以省略 org.elasticsearch 前缀。 Appender 部分包含日志描述信息。

正常情况下不要禁止日志的产生,可以通过提高日志的级别来控制日志的数量。系统日志每日会生成一个新的文件。

API

支持功能

1.检查集群,节点和索引的情况,状态和统计

2.管理集群,节点,索引数据和文档数据

3.执行CRUD 操作,可以对索引进行操作

4.执行高级搜索操作,如分页,排序,过滤,脚本,聚合和其他操作。

停止

ElasticSearch

1.如果节点是连接到控制台,按下Ctrl+C
2.杀进程。kill-xxx
命令

GET _cat/health

GET _cat/nodes

等待黄色集群状态。当节点加入集群后,首先恢复存储在本地的主分片数据。最初,通过_cat/health请求发现集群的状态时红色,表示不是所有的主分片都已分配。当每个节点都恢复完成后,集群的状态变成黄色,表示所有主分片已经被找到,但不是所有的副本分片都恢复。

重新分配:

延迟副本的分配直到所有节点都加入集群,在集群的所有节点,可以重新启动碎片分配:

PUT/_cluster/settings{
 "persistent":{"cluster.routing.allocation.enable":"all"}

}

此时集群开始复制所有副本到数据节点上,可以安全的恢复索引和搜索。延迟索引和搜索直到所有的分片都已恢复,可以加快集群的恢复。

通过API监控恢复的进度和监控情况:

GET _cat/health
GET _cat/recovery
当集群状态为绿色时,表示本次集群升级全部完成。

滚动升级

ElasticSearch 通常可以使用滚动升级过程,保证服务不中断。滚动升级允许ES 集群升级一个节点,同时又不影响系统的使用。

滚动升级步骤:

1.关闭分片分配。当我们关闭一个节点时,ES会立即试图复制这个节点的数据到集群的其他节点上,这会导致大量的IO请求,通过命令避免此问题产生:

PUT /_cluster/settings
{
 "transient":{"cluster.routing.allocation.enable": "none"}
}

2.停止不必要的索引和执行同步刷新。可以在升级过程中继续索引。但如果暂停不必要的索引碎片,则可以提升恢复的速度。当任何索引操作失败时,可以执行同步刷新操作:

POST /_flush/synced
 

对外接口: ElasticSearch 对外提供的API 是以HTTP 协议的方式,通过JSON 格式以rest 约定对外提供。

http 配置文件是放在ElasticSearch.yml 中,注意,所有与http 配置相关的内容都是静态配置,也就是需要重启后才生效。http 对外接口模块是可以禁用的,只需要设置http.enabled 为false 即可。 ElasticSearch 集群中的通信是通过内部接口实现的,而不是http 协议。在集群中不需要所有节点都开启http 协议,正常情况下,只需要在一个节点上开启http 协议。


API 约定: 

1.多索引参数:大多数API支持多索引查询,就是同时可以查询多个索引中的数据。

2.日期筛选:日期筛选可以限定时间序列索引的搜索范围,而不是全部内容,通过时间限定,可以从集群中减少搜索的内容,提高搜索效率和减少资源占用。

3.通用参数:

  3-1.pretty 参数,当你在任何请求中添加了参数?pretty=true 时,请求的返回值时经过格式化后的JSON数据,这样阅读起来更加的方便,系统还提供了另一种格式化?format=yaml ,yaml格式,这将导致返回的结果具有可读的yaml 格式。

  3-2.human 参数,对于统计数据,系统支持计算机数据,同时也支持比较适合人类阅读的数据。

  3-3.日期表达式,大多数参数接受格式化日期表达式,如范围查询gt(大于),lt(小于),或在日期聚合中用from to 来表达时间范围,表达式设定的日期为now 或者日期字符串加 ||。

   +1h 增加一小时
   -1D 减少一小时
    /D 上一小时

支持的时间单位: y(年),M(月),w(周),d(日),h(小时),m(分钟),s(秒)

例子:
   1.now + 1h: 当前时间加1小时,以毫秒为单位
   2.now + 1h+1m: 当前时间加1小时和一分钟,以毫秒为单位
   3.now + 1h/d : 当前时间加1小时,四舍五入到最近的一天。
 
响应过滤: 所有的返回值可以通过filter_path 来减少返回值的内容,多个值可以用逗号分开。

基于URL的访问控制: 当多用户通过URL 访问 ElasticSearch 索引的时候,为了防止用户误删除操作,可以通过基于URL 的访问控制来限制用户对某个具体索引的访问,在配置文件中添加参数:rest.action.multi.allow_explicit_Index: false ,这个参数默认为true。当该参数为false 时,在请求参数中指定具体索引的请求将会被拒绝。

启动ElasticSearch:  ------》cmd C:\tools\elasticSearch\elasticsearch-6.8.7\bin  ---》   elasticsearch.bat

启动ElasticSearch 控制台 --->进入 cmd 

cd C:\tools\elasticSearchHead\elasticsearch-head-master

npm run start

访问:http://127.0.0.1:9200/  访问 :Node Exporter

head 显示集群状态未连接解决方案,在elasticsearch config 文件夹的elasticsearch.yml 最下面加:

http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length, X-User"

1.

创建库:postman 以put 的形式输入下面的url 进行提交
http://127.0.0.1:9200/secisland?pretty

查询一下库的状态:浏览器访问下面的url,显示如图:
http://127.0.0.1:9200/_cat/indices?v

启动kibana:  进入 C:\tools\kibana\kibana-6.3.2-windows-x86_64\bin

启动:kibana.bat

输入:http://127.0.0.1:5601 ,进入Dev tools 将显示es 信息

查看集群健康状态:

新建索引 PUT:

 http://127.0.0.1:9200/articleindex/

put /indexName

新建文档 POST

http://127.0.0.1:9200/articleindex/article

{
    "title":"小胖子凹凸曼",
    "content":"世界就像一个巨大的夹娃娃机,隔着玻璃,我只想得到你"
}

http://127.0.0.1:9200/articleindex/article/abcdef

{"title":"张杰",
 "content":"眸光流转,仿若花开"
}

查看索引下某类型的全部数据 GET

 http://127.0.0.1:9200/articleindex/article/_search

模糊查询 GET

http://127.0.0.1:9200/articleindex/article/_search?q=title:*眸光流转*

删除数据 DELETE

 http://127.0.0.1:9200/articleindex/article/abcdef  

 查看有哪些索引: GET /_cat/indices?v


删除索引:delete /indexName

创建文档: put /inde /type /id
PUT /ecommerce/product/1
{
  "name": "gaolujie yagao",
  "desc": "gaolujie meibai",
  "price": 30,
  "producer":"gaolujie producer",
  "tags":["meibai","fangzhu"]
}


PUT /ecommerce/product/2
{
  "name": "jiajieshi yagao",
  "desc": "jiajieshi fangzhu",
  "price": 30,
  "producer":"jiajieshi producer",
  "tags":["fangzhu"]
}
PUT /ecommerce/product/3
{
  "name": "zhonghua yagao",
  "desc": "zhonghua caoben",
  "price": 30,
  "producer":"zhonghua producer",
  "tags":["qingxin"]

注意:ES 会自动建立index 和type ,不需要提前创建,而且ES 默认会对document每个field 建立倒排索引,让它可以被搜索到。

document 的全量替换:与创建文档一样,如果document id 不存在,那么就是创建,如果已存在,那么就是全量替换。

document 强制创建:

PUT /index/type/id/_create

获取文档: GET /ecommerce/product/1

_source 元数据:我们在创建document 的时候,使用的那个放在request body 种的json 串,默认情况下,在get 的时候,会原封不动的给我们返回。

定制返回结果:
1.method1: 返回文档的全部数据:
GET /ecommerce/product/1

2.method2:返回文档的只想要的数据[多个字段用逗号分开]:
GET /ecommerce/product/1?_source=name,desc

修改商品:

 method1:替换文档[需要所有的字段都带上]
 
PUT /ecommerce/product/1
{
 "name":"jiaqianban gaolujie yagao",
 "desc":"gaolujie meibai",
 "producer":"gaolujie producer",
 "tags":["meibai","fangzhu"]
}

ES基于_version乐观锁修改数据[版本号必须等于当前的版本]:
 PUT /ecommerce/product/1?version=2
{
  "name":"gaolujie yagao"
}

基于external version 修改数据[版本号必须大于当前的版本]:
PUT /ecommerce/product/1?version=4&version_type=external
{
  "name":"gaolujiea yagao"
}

external version : es 提供了一个feature,可以不用它提供的内部_version 版本号来进行并发控制,可以基于自己维护的一个版本号来进行并发控制。例如,加入你的数据在MySQL 里也有一份,然后你的应用本身就维护了一个版本号,无论时什么自己生成的,程序控制的。这个时候,你进行乐观锁并发控制的时候,可能并不想要用ES内部的_version 来进行控制的,而是用你自己维护的那个version 来进行控制。

  method2:更新文档[更新你想更新的字段]
POST /ecommerce/product/1/_update
{
  "doc":{
    "name":"gaolujie"
  }
}

partial update 相较于全量替换的优点[其实内部是先将文档标记为删除,再新建文档]:
1.所有的查询,修改,和写回操作,都发生在ES中的一个shard 内部,避免了所有的网络数据传输的开销(减少2次网络请求),大大提升了性能。

2.减少了查询和修改中的时间间隔,可以有效减少并发冲突的情况。

删除文档: DELETE /ecommerce/product/1

注意:删除机制不是立即物理删除,而是将其标记为deleted,当数据越来越多时,ES 才会自动删除已经标记过的数据。

6种查询方式:[query string search | query dsl | query filter | full-text search |  phrase search  highlight search]

1.query string search
例子:
  1.搜索全部商品:GET /ecommerce/product/_search
  2.搜索商品名称包含xxx 的商品,而且按照售价降序排序: GET /ecommerce/product/_search?q=name:yagao&sort=price:desc

2.query dsl
例子:
1.搜索全部商品:
GET /ecommerce/product/_search
{
  "query":{
    "match_all":{}
    
  }
}
2.搜索商品名称包含xxx 的商品,而且按照售价降序排序:
GET /ecommerce/product/_search
{
  "query":{
    "match":{
     "name":"yagao" 
    }
  },
  "sort":[{
      "price":"desc"
    }]
}
3.分页查询商品:
GET /ecommerce/product/_search
{
  "query":{
    "match_all":{}
  },
  "from":1,
  "size":1
}
4.指定要查询出来的字段:
GET /ecommerce/product/_search
{
  "query":{
    "match_all":{}
  },
  "_source":["name","price"]
}


3 query filter
筛选出名称等于yagao,且价格大于25的有哪些商品:
GET/ecommerce/product/_search{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "name": "yagao"
                }
            },
            "filter": {
                "range": {
                    "price": {
                        "gt": 25
                    }
                }
            }
        }
    }
}

4 full-text search
匹配度越高,越靠前
GET /ecommerce/product/_search
{
  "query":{
    "match":{
      "producer": "heiren producer"
    }
  }
}

5 phrase search
跟全文检索相对应,相反,全文检索会将输入的搜索串拆解开来,去倒排索引,只要能匹配到任意一个拆解后的单词,就可以作为结果返回。短语检索,要求输入的搜索串,必须在指定的字段文本中,完全包含一摸一样的,才可以算匹配,作为结果返回。

GET /ecommerce/product/_search
{
  "query":{
    "match_phrase":{
      "producer": "heiren producer"
    }
  }
}

6 highlight search

GET /ecommerce/product/_search
{
  "query":{
    "match_phrase":{
      "producer": "producer"
    }
  },
  "highlight": {
    "fields": {
      "producer": {}
    }
  }
}                                            

took: 耗费了几毫秒
timed_out: 是否超市,这里是没有
_shards: 数据拆成了5个分片
hits.total:数据结果的数量,3个document
max_score: 就是document 对于一个search 的相关度的匹配分数,越相关,分数越高

hits.hits:包含了匹配搜索的document 的详细数据。

学习ES聚合:

1.修改tags 类型:

PUT /ecommerce/_mapping/product
{
  "properties": {
    "tags":{
      "type":"text",
      "fielddata":true
    }
  }
}
2.检索每个tag 下有几条数据
GET /ecommerce/product/_search
{
    "size": 0,
    "aggs": {
        "group_by_tags": {
            "terms": {
                "field": "tags"
            }
        }
    }
}

3.对名称包含yagao 的商品,计算每个tag 下的商品数量
GET /ecommerce/product/_search
{
    "size": 0,
    "query": {
        "match": {
            "name": "yagao"
        }
    },
    "aggs": {
        "group_by_tags": {
            "terms": {
                "field": "tags"
            }
        }
    }
}
4.先分组,再算每组的平均值,计算每个tag 下的商品的平均价格
GET /ecommerce/product/_search
{
    "size": 0,
    "aggs": {
        "groub_by_tags": {
            "terms": {
                "field": "tags"
            },
            "aggs": {
                "avg_price": {
                    "avg": {
                        "field": "price"
                    }
                }
            }
        }
    }
}

5.先分组,再算每组的平均值,计算每个tag 下的商品的平均价格,且按照平均价格排序

GET /ecommerce/product/_search
{
    "size": 0,
    "aggs": {
        "groub_by_tags": {
            "terms": {
                "field": "tags",
                "order": {
                    "avg_price": "desc"
                }
            },
            "aggs": {
                "avg_price": {
                    "avg": {
                        "field": "price"
                    }
                }
            }
        }
    }
}

6.按照指定价格范围区间进行分组,然后再每组内再按照tag进行分组,最后再计算每组的平均价格
GET/ecommerce/product/_search
{
    "size": 0,
    "aggs": {
        "groub_by_tags": {
            "range": {
                "field": "price",
                "ranges": [{
                    "from": 0,
                    "to": 20
                },
                {
                    "from": 20,
                    "to": 50
                },
                {
                    "from": 50,
                    "to": 100
                }]
            },
            "aggs": {
                "group_by_tags": {
                    "terms": {
                        "field": "tags"
                    },
                    "aggs": {
                        "average_price": {
                            "avg": {
                                "field": "price"
                            }
                        }
                    }
                }
            }
        }
    }
}
 

master节点: master 节点不承载所有的请求,所以不会是一个单点瓶颈。

1.管理ES 集群的元数据:比如索引的创建和删除,维护索引元数据;节点的增加和移除,为维护集群的元数据。

2.默认情况下,会自动选择出一台节点,作为master 节点。

ES提升性能:

1.primary & replica 自动负载均衡

2.动态修改replica 数量。

ES容错:

1.自动选举master
2.重启故障的node,new master,会将确实的副本都copy 一份到该node 上,而且该node 会使用之前已有的shard 数据,只是同步一下宕机之后发生过的修改。

《第二章:索引》

索引:索引是具有相同结构的文档集合。在ElasticSearch 中索引是个非常重要的内容,对ElasticSearch 的大部分都是基于索引来完成的。

创建索引的时候可以通过修改number_of_shards & number_of_replicas 参数的数量来修改分片和副本的数量。默认情况下分片的数量是5个,副本的数量是1个。

例子【postman】:

1.创建3个主分片,两个副本分片的索引。

【put】 http://127.0.0.1:9200/fenghuang/
 参数[方法一]:
{
  "index":{"number_of_shards":3,"number_of_replicas":2}
}

参数[方法二]
{
 "settings":{"number_of_shards":3,"number_of_replicas":2}

2.完成对副本数量的修改
【put】http://127.0.0.1:9200/fenghuang/_settings/
{
  "number_of_replicas":5
}

3.对于ElasticSearch 文档而言,一个文档会包括一个或者多个字段,任何字段都要有自己的数据类型,例如string,integer,date 等。ElasticSearch 中是通过映射来进行字段和数据对应的。在默认情况下,ES 会自动识别字段的数据类型,同时ES提供了mappings 参数可以显式的进行映射。

4.删除索引:
【delete】 http://127.0.0.1:9200/secisland/

注意:删除索引需要指定索引名称,别名或者通配符。删除索引可以使用逗号分隔符,或者使用—_all 或者 * 号删除全部索引。

【get】获取索引:http://127.0.0.1:9200/secisland/    http://127.0.0.1:9200/_all

 注意:获取索引可以使用通配符获取多个索引,使用_all 或者 * 号获取全部索引。获取不存在的索引,系统会返回一个错误的内容。
 
 5.打开 /关闭索引:打开or 关闭索引接口允许关闭一个打开的索引或者打开一个已经关闭的索引。关闭的索引只能显示索引元数据信息,不能够进行读写操作。
 
 关闭索引:
 【post】 http://127.0.0.1:9200/secisland/_close 
 打开索引:
 【post】 http://127.0.0.1:9200/secisland/_open
 
 注意:因为关闭的索引会继续占用磁盘空间而不能使用,索引关闭索引接口可能会造成磁盘空间的浪费。
  

1.添加映射:api 允许向索引index 添加文档类型type,或者向文档类型type 中添加字段field。

1.[put]:http://127.0.0.1:9200/secisland
{
    "mappings":{
        "log":{
            "properties":{
                "message":{"type":"log"}
            }
        }
    }
}
解释:添加索引名为secisland,文档类型为log,其中包含字段message,字段类型为字符串。 

2.[put] http://127.0.0.1:9200/secisland/_mapping/log
{
 "properties":{
   "user_name" :{"type": "string"}
 }
}
解释:已经存在的索引secisland,文档类型为log,添加新的字段user_name,字段类型为字符串。

1.批量查询[减少网络开销,网络传输]:

GET/_mget{
    "docs": [{
        "_index": "ecommerce",
        "_type": "product",
        "_id": "1"
    },
    {
        "_index": "secisland",
        "_type": "secilog",
        "_id": "1"
    }]
}

2.查询的document 是一个index下的不同type :

GET/ecommerce/_mget{
    "docs": [{
        "_type": "product",
        "_id": "1"
    },
    {
        "_type": "secilog",
        "_id": "2"
    }]
}

3.查询同一个index 下同一type:

GET/ecommerce/product/_mget{
    "docs": [{
        "_id": "1"
    },
    {
        "_id": "2"
    }]
}

bulk:批量增删改:

bulk api 对json 的语法,有严格要求,每个json 串不能换行,只能放一行。同时一个json 串 和一个json串之间,必须有一个换行。
注意:bulk 操作中,任意一个操作失败,是不会影响其他的操作的,但是再返回结果里,会告诉你异常的日志。

bulk size 最佳大小: bulk request 会加载到内存里,如果太大的化,性能反而会下降,因此需要反复尝试一个最佳的bulk size。
一般从1000~5000条数据开始,尝试逐渐增加。另外,如果看大小的话,最好再5~15MB 之间。

路由算法: shard = hash(routing) % number_of_primary_shard

每次增删改查document 的时候,都会带过来一个routing number ,默认就是这个document 的id,也可以手动指定。决定一个document 在哪个shard 上,最重要的一个值就是routing值,相同的routing值,每次从hash 函数中生成的一定是相同的。手动指定routing value 的重要性,可以保证,某一类document 一定被路由到一个shard 上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候十分重要。

例如:put/index/type/id?routing=user_id。

写一致性quorum:one(primary shard), all(all shard),quorum(default)

我们在发送任何一个增删改操作:put /index/type/id?consistency=one 都可以带上一个consistency 参数

one:要求我们写操作时,只要有一个primary shard 是active 活跃可用的,就可以执行。

all:要求我们写操作时,必须所有的primary shard 和replica shard 都是活跃的,才可以执行这个操作。

quorum: 默认值,要求所有的shard 中,必须是大部分的shard 都是活跃的,可用的,才可以执行这个写操作。

搜索:

/_search : 所有索引,所有type下的所有数据

/index/_search:指定index下的所有type 类型数据

/index,index/_search: 指定多个index下的搜友type 类型数据

/*1,*2/_search: 按照通配符去匹配多个索引

/index/type/_search:指定index下的指定type 类型数据

/index/type,type/_search :指定index下的多个指定type 类型数据

/_all/type,type/_search:_all,可以代表搜索所有index 下的指定type 数据

GET /ecommerce/product/_search?q=name:heiren

分页显示:GET /ecommerce/product/_search?from=0&size=2

查看index 的type document 的各个字段的类型:GET /ecommerce/_mapping/product

normalization 分词器:提升recall 召回率。

mapping:不同的数据类型,mapping可能不同。exact value & full text 类型的field 决定了搜索的行为,回跟倒排索引的行为保持一致;

string byte,short integer long float double boolean date 

analyzed not_analyzed no

注意:只能创建index 的时候就手动建立mapping,或者新增field mapping,但不能修改已有的field mapping。

手动指定数据类型:
PUT /website
{
  "mappings":{
   "artice":{
     "properties":{
       "content":{
         "type":"text",
         "analyzer":"english"
       },
       "post_date":{
         "type":"date"
       },
       "name":{
         "type":"text"
       },
       "author_id":{
         "type":"long"
       }
     }
   } 
  }
}
添加数据含有对象:
PUT /company/employee/1
{
  "name":"jack",
  "join_date":"2020-12-20",
  "address":{
    "country":"china",
    "province":"guangzhou",
    "city":"shenzhen"
  }
}

查询所有:
GET _search
{
  "query":{
    "match_all": {}
  }
}
根据字段进行查询:
GET /ecommerce/product
{
  "query":{
    "name": "gaolujie"
  }
}

GET/ecommerce/product/{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "name": "tom"
                }
            },
            "should": [{
                "match": {
                    "hired": true
                }
            },
            {
                "bool": {
                    "must": {
                        "match": {
                            "personality": "good"
                        }
                    },
                    "must_not": {
                        "match": {
                            "rude": true
                        }
                    }
                }
            }],
            "minimum_should_match": 1
        }
    }
}


GET/ecommerce/product/{
    "query": {
        "bool": {
            "must": [{
                "match": {
                    "name": "nihao"
                }
            }],
            "filter": {
                "range": {
                    "age": {
                        "gte": 30
                    }
                }
            }
        }
    }
}

filter 与query 对比:

1.搜索场景:filter ,仅仅只是按照搜索条件过滤出需要的数据而已
query,会去计算每个document 相对于搜索条件的相关度,并按照相关度进行排序。
一般来说,如果你在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter。

2.filter 与query 性能:
filter 不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache 最常用的filter的功能。
query,要计算相关度分数,按照分数进行排序,而且无法cache结果。

GET /ecommerce/product/
{
  "query":{
    "multi_match": {
      "query": "heiren",
      "fields": ["price","name"]
    }
  }
}

查询区间:
GET /ecommerce/product/
{
  "query":{
    "range": {
      "price":{
        "gte": 10,
        "lt":70
      }
    }
  }
}

term query: 不进行分词的匹配

GET /ecommerce/product/_search
{
  "query":{
    "term": {
      "name":"heiren"
    }
  }
}

GET/ecommerce/product/_search{
    "query": {
        "term": {
            "name": "yagao"
        }
    },
    "sort": [{
        "_id": {
            "order": "asc"
        }
    }]
}

relevance score算法,计算出一个索引中的文本,与搜索文本,它们之间的关联匹配程序。

ES使用的是term frequency/inverse document frequency 算法。简称TF/IDF算法。

Term frequency: 搜索文本中的各个词条在field 文本中出现了多少次,出现的次数越多,就越相关。

Inverse document frequency: 搜索文本中的各个词条在field 文本中出现了多少次,出现的次数越多,就越不相关。

搜索的时候依靠倒排索引,排序的时候,需要依靠正排索引,看到每个document的每个field,然后进行排序,馊味的正排索引,就是doc values。 在建立索引的时候,一方面会建立倒排索引,以供搜索用;一方面会建立正排索引,也就是doc values。
以供排序,聚合,过滤等操作使用。

doc 是被保存在磁盘上的,此时如果内存足够,os 会自动将其缓存在内存中,性能还是会很高;如果内存不够,os 会将其写入磁盘上。
 

滚动查询,采用基于_doc进行排序,性能较高:
GET /ecommerce/product/_search?scroll=1m
{
  "query":{
    "match_all": {}
  },
  "sort":["_doc"],
  "size":3
}
避免误删全部索引
action.destructive_requires_name: true

创建分词器:
PUT /my_index
{
  "settings":{
    "analysis":{
      "analyzer":{
        "es_std":{
          "type":"standard",
          "stopwords":"_english_"
        }
      }
    }
  }
}

启用停用词:
GET /my_index/_analyze
{
  "analyzer":"es_std",
  "text":"a dog is in the house"
}

创建自定义分词:
PUT my_index2
{
 "settings":{
   "analysis":{
     "char_filter":{
       "&_to_and":{
         "type":"mapping",
         "mappings":["&=> and"]
       }
     },
     "filter":{
       "my_stopwords":{
         "type":"stop",
         "stopwords":["the","a"]
       }
     },
     "analyzer":{
       "my_analyzer":{
         "type":"custom",
         "char_filter":["html_strip","&_to_and"],
         "tokenizer":"standard",
         "filter":["lowercase","my_stopwords"]
       }
     }
   }
 } 
}

1.重建索引:一个field 的设置是不能被修改的,修过当前field 类型不能满足现有的需求,难么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api 写入index 中批量查询出来的时候,建议采用scroll api,并且采用多线程并发的方式来reindex 重置数据,每次scoll 就查询指定日期的一段数据,交给一个线程即可。

GET /old_index/_search?scroll=1m
{
  "query":{
    "range":{
     "date":{
      "gte":"2017-01-11",
      "lt": "2017-11-12"
     }
    }
  },
  "sort":["_doc"],
  "size":1000
}

2.重建索引,将旧索引的数据查询出来,再导入新索引。

PUT/my_index/new{
    "mappings": {
        "my_type": {
            "properties": {
                "title": {
                    "type": "text"
                }
            }
        }
    }
}

3.如果说旧索引的名字,是old_index,新索引的名字是new_index,终端Java 应用,已经在使用old_index 在操作了,此刻给Java应用一个别名,这个别名是指向旧索引的,Java应用先用者,Java应用先用goods_index alias 来操作,此时实际指向的是旧的my_index。

PUT /my_index/_alias/goods_index

4.采用bulk api 将滚动查询的数据批量写入新索引

POST /_bulk
{
 "index":"{"_index":"my_index_new","_type":"my_type","_id":2"}
}
{
  "title":"2017-01-01"
}

将goods_index alias 切换到my_index_new 上去,Java应用会直接通过index别名使用新的索引中的数据,Java 应用程序不需要停机,零提交,高可用。

POST /_aliases
{
  "actions":[
   {"remove":{"index":"my_index","alias":"goods_index"}},
   {"add":{"index":"my_index_new","alias":"goods_index"}}
   
  ]
}

倒排索引的结构:
1.包含这个关键词的document list
2.包含这个关键词的所有document 的数量:IDF: inverse document frequency
3.这个关键词在每个document 中出现的次数:TF: term frequency
4.这个关键词在这个document 中的次序
5.每个document 的长度:length norm
6.包含这个关键词的所有document 的平均长度

倒排索引不可变的好处:

1.不需要锁,提升并发能力,避免锁的问题
2.数据不变,一直保存在os cache 中,只要cache 内存足够
3.filter cache 一致贮存在内存,因为数据不变
4.可以压缩,节省CPU & io 开销

倒排索引的缺点: 每次都要重新构建整个索引。

#获取所有索引库索引库信息
GET _cat/indices?v

# 删除索引库
DELETE /.monitoring-kibana-6-2020.05.23

# 添加索引库
PUT /userinfo

#添加索引mapping映射

PUT /userinfo/emp/_mapping
{
  "properties": {
    "name":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    },
    
    "city":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    },
    
     "age":{
      "type":"integer", 
      "store":true
    },
    
     "description":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    }
    
  }
}

#向文档中新插入一条记录

POST userinfo/emp/1
{
  "name":"张三",
  "city":"shanghai",
  "age":21,
  "description":"我是张三"
}


POST userinfo/emp/2
{
  "name":"李四",
  "city":"shanghai",
  "age":22,
  "description":"我是李四"
}

#修改和新增一样:无则新增,有则修改[内部原理是先删除后添加]
POST userinfo/emp/3
{
  "name":"王五",
  "city":"shanghai",
  "age":22,
  "description":"我是王五"
}

POST userinfo/emp/4
{
  "name":"i'm jack",
  "city":"uc",
  "age":25,
  "description":"i from uc"
}

POST userinfo/emp/5
{
  "name":"i'm Bruce Lee",
  "city":"uc",
  "age":27,
  "description":"i'm Bruce Lee"
}
#在文档中删除一条记录

DELETE userinfo/emp/1

#根据id查询

GET userinfo/emp/4

#根据关键词进行查询[使用标准的分词器,一个字一个分词,如果直接搜张三,则搜索不到哦]
POST userinfo/emp/_search
{
  "query":{
    "term":{
      "name":"张"
    }
  }
}

#querystring查询[字符串搜索]
POST userinfo/emp/_search
{
  "query":{
    "query_string": {
      "default_field": "description",
      "query": "李四"
    }
  }
}

#should      【or 或的关系】
#must        【等于】
#term        【关键词查询】
#query_string【字符串查询】
#fuzzy       【模糊查询】
#wildcard    【通配符查询】
#prefix      【前缀查询】
#range       【区间查询】

#获取所有索引库索引库信息
GET _cat/indices?v

# 删除索引库
DELETE /.monitoring-kibana-6-2020.05.23

# 添加索引库
PUT /blog

#添加索引mapping映射和默认分词(standard)【6.8.7】

PUT /userinfo/emp/_mapping
{
  "properties": {
    "name":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    },
    
    "city":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    },
    
     "age":{
      "type":"integer", 
      "store":true
    },
    
     "description":{
      "type":"text", 
      "analyzer": "standard",
      "search_analyzer": "standard",
      "store":true
    }
    
  }
}

#添加索引mapping映射和中文分词器【7.7.0】

PUT /blog/book/_mapping?include_type_name=true
{
  "properties": {
    "name":{
      "type": "text", 
      "analyzer": "ik_smart",
      "search_analyzer": "ik_smart",
      "store":true
    },
    
    "city":{
      "type":"text",
      "analyzer": "ik_smart",
      "search_analyzer": "ik_smart",
      "store":true
    },
    
     "age":{
       "type":"integer",
      "store":true
    },
    
     "description":{
       "type": "text", 
      "analyzer": "ik_smart",
      "search_analyzer": "ik_smart",
      "store":true
    }
    
  }
}

#向文档中新插入一条记录

POST blog/book/1
{
  "name":"张三",
  "city":"shanghai",
  "age":21,
  "description":"我是张三"
}


POST blog/book/2
{
  "name":"李四",
  "city":"shanghai",
  "age":22,
  "description":"我是李四"
}

#修改和新增一样:无则新增,有则修改[内部原理是先删除后添加]
POST blog/book/3
{
  "name":"王五",
  "city":"shanghai",
  "age":22,
  "description":"我是王五"
}

POST blog/book/4
{
  "name":"i'm jack",
  "city":"uc",
  "age":25,
  "description":"i from uc"
}

POST blog/book/5
{
  "name":"i'm Bruce Lee",
  "city":"uc",
  "age":27,
  "description":"i'm Bruce Lee"
}

POST blog/book/6
{
  "name":"我是中国人,我爱中国,中国是中华民族的伟大母亲,华夏文明的发源地,四大文明古国的孕育摇篮",
  "city":"中国",
  "age":27,
  "description":"我是中国人,我爱中国,中国是中华民族的伟大母亲,华夏文明的发源地,四大文明古国的孕育摇篮"
}
#在文档中删除一条记录

DELETE userinfo/emp/1

#根据id查询

GET userinfo/emp/4

#根据关键词进行查询[使用标准的分词器,一个字一个分词,如果直接搜张三,则搜索不到哦]
POST userinfo/emp/_search
{
  "query":{
    "term":{
      "name":"张"
    }
  }
}

#querystring查询[字符串搜索]
POST userinfo/emp/_search
{
  "query":{
    "query_string": {
      "default_field": "description",
      "query": "李四"
    }
  }
}

#should      【or 或的关系】
#must        【等于】
#term        【关键词查询】
#query_string【字符串查询】
#fuzzy       【模糊查询】
#wildcard    【通配符查询】
#prefix      【前缀查询】
#range       【区间查询】

# standard   【es标准分词器】
# ik_smart   【最少切分】
# ik_max_word【最细粒度划分】

#elasticsearch【7.7.0创建分词写法】
GET /_analyze
{
  "analyzer" : "ik_smart",
  "text" : "我是中国人,我爱中国,中国是中华民族的伟大母亲,华夏文明的发源地,四大文明古国的孕育摇篮"
}

POST blog/book/_search
{
  "query":{
    "term": {
      "name": {
        "value": "摇篮"
      }
    }
  }
}

索引时最好不要进行加权,主要有这几个原因:
1.除非重索引所有的文档,索引加权值不会发生改变。
2.每个查询都支持查询加权,会产生同样的效果。不同的地方在于不需要重索引就可以调整加权值。
3.索引加权值作为norm的一部分,只有一个字节。这降低了字段长度归一化因子的分辨率,会导致低质量的相关性计算。

索引加权的唯一优势在于作用于_all字段,当查询_all字段的时候,源于title字段的词比源于content字段的词有更高的分数。这个功能是以计算成本为代价的:当索引加权被使用时,查询_all字段会变得更加缓慢。

coerce 参数:强制尝试清理脏值来匹配字段的数据类型。
1.字符串会被强制转换为数字
2.浮点型数据会被截取为整型数据。
3.经纬地理点数据会归一化到标准-180:180/-90:90坐标系统。

put http://127.0.0.1/secisland
{
    "mappings":{
    "secilog":{
    "properties":{
    "number_one":{"type":"integer"},
    "number_tow":{
    "type":"integer",
    "coerce":false
    }
    }
    }
    }
}
 

java 操作elasticsearch 7.x  es.rar关于elasticsearch的增删改查-互联网文档类资源-CSDN下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值