Elasticsearch 概述
Elasticsearch是一个基于lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。
ELK 技术栈是Elasticsearch、Logstash、Kibana三大开元框架首字母大写简称。
而Elasticsearch 是一个开源的高扩展的分布式全文搜索引擎, 是整个 ELK技术栈的核心。
Elasticsearch是一个基于lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。
Logstash是中央数据流引擎,用于从不同目标(文件/数据存储/mq)收集不同格式的数据,经过过滤后支持输出到不同目的地
Kibana可以将es的数据通过友好的页面展示出来,提供实时分析的功能
关于全文检索引擎
这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
关系型数据库的全文检索功能缺点
首先就mysql而言,数据库用来存储文本字段本身就与关系型的思想相悖,而且全文检索时需要全表扫描,大数据量下即使对sql语句进行优化,响应时间也很难以满足需求。即使建立索引,而且是可能大量的建立索引来优化,反而维护更麻烦,insert和update每次又都会重新构建索引,反而增加了数据库的压力。
全文检索的应用场景
检索的数据对应是大量的非结构化的文本型数据
文件的记录量至少是十万以上级别
支持交互式文本的全文检索查询
对于检索结果的相关性具有较高的要求,且检索的实时性要求很高
Elasticsearch 应用案例
GitHub: 2013 年初,抛弃了 Solr,采取 Elasticsearch 来做 PB 级的搜索。 “GitHub 使用Elasticsearch 搜索 20TB 的数据,包括 13 亿文件和 1300 亿行代码”。
- 维基百科:启动以 Elasticsearch 为基础的核心搜索架构
- 百度:目前广泛使用 Elasticsearch 作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部 20 多个业务线(包括云分析、网盟、预测、文库、直达号、钱包、 风控等),单集群最大 100 台机器, 200 个 ES 节点,每天导入 30TB+数据。
- 新浪:使用 Elasticsearch 分析处理 32 亿条实时日志。
- 阿里:使用 Elasticsearch 构建日志采集和分析体系。
全文搜索引擎
Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:
- 搜索的数据对象是大量的非结构化的文本数据。
- 文件记录量达到数十万或数百万个甚至更多。
- 支持大量基于交互式文本的查询。
- 需求非常灵活的全文搜索查询。
- 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
- 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。
- 为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎
这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
Elasticsearch And Solr
Lucene 是 Apache 软件基金会 Jakarta 项目组的一个子项目,提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java 开发环境里 Lucene 是一个成熟的免费开源工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。但 Lucene 只是一个提供全文搜索功能类库的核心工具包,而真正使用它还需要一个完善的服务框架搭建起来进行应用。
目前市面上流行的搜索引擎软件,主流的就两款:Elasticsearch 和 Solr,这两款都是基于 Lucene 搭建的,可以独立部署启动的搜索引擎服务软件。由于内核相同,所以两者除了服务器安装、部署、管理、集群以外,对于数据的操作 修改、添加、保存、查询等等都十分类似。
在使用过程中,一般都会将 Elasticsearch 和 Solr 这两个软件对比,然后进行选型。这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 - Lucene 构建的 - 但它们又是不同的。像所有东西一样,每个都有其优点和缺点:
Elasticsearch Or Solr
Elasticsearch 和 Solr 都是开源搜索引擎,那么我们在使用时该如何选择呢?
- Google 搜索趋势结果表明,与 Solr 相比,Elasticsearch 具有很大的吸引力,但这并不意味着 Apache Solr 已经死亡。虽然有些人可能不这么认为,但Solr 仍然是最受欢迎的搜索引擎之一,拥有强大的社区和开源支持。
- 与 Solr 相比,Elasticsearch 易于安装且非常轻巧。此外,你可以在几分钟内安装并运行Elasticsearch。但是,如果 Elasticsearch 管理不当,这种易于部署和使用可能会成为一个问题。基于 JSON 的配置很简单,但如果要为文件中的每个配置指定注释,那么它不适合您。总的来说,如果你的应用使用的是 JSON,那么 Elasticsearch 是一个更好的选择。否则,请使用 Solr,因为它的 schema.xml 和 solrconfig.xml 都有很好的文档记录。
- Solr 拥有更大,更成熟的用户,开发者和贡献者社区。ES 虽拥有的规模较小但活跃的用户社区以及不断增长的贡献者社区。Solr 贡献者和提交者来自许多不同的组织,而 Elasticsearch 提交者来自单个公司。
- Solr 更成熟,但 ES 增长迅速,更稳定。
- Solr 是一个非常有据可查的产品,具有清晰的示例和 API 用例场景。 Elasticsearch 的文档组织良好,但它缺乏好的示例和清晰的配置说明。
那么,到底是 Solr 还是 Elasticsearch?
有时很难找到明确的答案。无论您选择Solr 还是 Elasticsearch,首先需要了解正确的用例和未来需求。总结他们的每个属性。
Ø 由于易于使用,Elasticsearch 在新开发者中更受欢迎。一个下载和一个命令就可以启动一切。
Ø 如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择
Ø 如果需要分布式索引,则需要选择Elasticsearch。对于需要良好可伸缩性和以及性能分布式环境,Elasticsearch 是更好的选择。
Ø Elasticsearch 在开源日志管理用例中占据主导地位,许多组织在 Elasticsearch 中索引它们的日志以使其可搜索。
如果你喜欢监控和指标,那么请使用 Elasticsearch,因为相对于 Solr,Elasticsearch 暴露了更多的关键指标
有时很难找到明确的答案。无论您选择Solr 还是 Elasticsearch,首先需要了解正确的用例和未来需求。总结他们的每个属性。
Ø 由于易于使用,Elasticsearch 在新开发者中更受欢迎。一个下载和一个命令就可以启动一切。
Ø 如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择
Ø 如果需要分布式索引,则需要选择Elasticsearch。对于需要良好可伸缩性和以及性能分布式环境,Elasticsearch 是更好的选择。
Ø Elasticsearch 在开源日志管理用例中占据主导地位,许多组织在 Elasticsearch 中索引它们的日志以使其可搜索。
如果你喜欢监控和指标,那么请使用 Elasticsearch,因为相对于 Solr,Elasticsearch 暴露了更多的关键指标
关于es检索的核心-倒排索引
在搜索引擎中每个文件都对应一个文件ID,文件内容被表示为一系列关键词的集合(实际上在搜索引擎索引库中,关键词也已经转换为关键词ID)。例如“文档1”经过分词,提取了20个关键词,每个关键词都会记录它在文档中的出现次数和出现位置。
正向索引(forward index)
得到正向索引的结构如下:通过key,去找value。
“文档1”的ID > 单词1:出现次数,出现位置列表;单词2:出现次数,出现位置列表;…………。
“文档2”的ID > 此文档出现的关键词列表。
正向索引的弊端:假设使用正向索引检索关键词"索引测试",那么需要扫描全库索引检索,然后根据某个权重策略进行排序返回给用户。问题就在于数据量十分庞大时的全库扫描无法满足实时的检索需求
倒排索引(inverted index)
搜索引擎会将正向索引重新建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词。
得到倒排索引的结构如下:从词的关键字,去找文档ID。
“关键词1”:“文档1”的ID,“文档2”的ID,…………。
“关键词2”:带有此关键词的文档ID列表。
Elasticsearch 入门
Elasticsearch 安装
下载软件
Elasticsearch 的官方地址:Elastic — The Search AI Company | Elastic利用 Elastic Search AI Platform 高效获得见解和推动成果转化。通过专为协助您更快获得洞察而设计的企业解决方案,深入了解您的数据并找到重要答案。立即试用 Elastic。...https://www.elastic.co/cn/
Elasticsearch 最新的版本是 7.11.2(截止 2021.3.10),我们选择 7.8.0 版本(最新版本半年前的版本)
下载地址:Past Releases of Elastic Stack Software | ElasticLooking for a past release of Elasticsearch, Logstash, Kibana, es-hadoop, Shield, Marvel, or our language clients? You're in the right place....https://www.elastic.co/cn/downloads/past-releases#elasticsearch
Elasticsearch 分为 Linux 和 Windows 版本,基于我们主要学习的是Elasticsearch 的Java
客户端的使用,所以我们使用的是安装较为简便的 Windows 版本。
安装软件
Windows 版的Elasticsearch 的安装很简单,解压即安装完毕,解压后的Elasticsearch 的目录结构如下
目录 | 含义 |
bin | 可执行脚本目录 |
config | 配置目录 |
jdk | 内置 JDK 目录 |
lib | 类库 |
logs | 日志目录 |
modules | 模块目录 |
plugins | 插件目录 |
解压后,进入bin 文件目录,点击 elasticsearch.bat 文件启动ES 服务
注意:9300 端口为 Elasticsearch 集群间组件的通信端口,9200 端口为浏览器访问的 http
协议 RESTful 端口。
打开浏览器(推荐使用谷歌浏览器),输入地址:http://localhost:9200,测试结果
问题解决
Ø Elasticsearch 是使用 java 开发的,且 7.8 版本的ES 需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,如果系统配置 JAVA_HOME,那么使用系统默认的 JDK,如果没有配置使用自带的JDK,一般建议使用系统配置的JDK。
Ø 双击启动窗口闪退,通过路径访问追踪错误,如果是“空间不足”,请修改config/jvm.options 配置文件
Elasticsearch 基本操作
RESTful
REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。
在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和DELETE。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、PUT、DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以及对资源进行的操作(增删改查)。
数据格式
Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解, 我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比
ES 里的 Index 可以看做一个库,而Types 相当于表,Documents 则相当于表的行。
这里Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个type,Elasticsearch 7.X 中, Type 的概念已经被删除了
用JSON 作为文档序列化的格式,比如一条用户信息
{
"name" : "John",
"sex" : "Male", "age" : 25,
"birthDate": "1990/05/01",
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
Elasticsearch 进阶
核心概念
索引(Index)
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。
能搜索的数据必须索引,这样的好处是可以提高查询速度,比如:新华字典前面的目录就是索引的意思,目录可以提高查询速度。
Elasticsearch 索引的精髓:一切设计都是为了提高搜索的性能。
类型(Type)
在一个索引中,你可以定义一种或多种类型。
一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。不同的版本,类型发生了不同的变化
版本 | Type |
5.x | 支持多种 type |
6.x | 只能有一种 type |
7.x | 默认不再支持自定义索引类型(默认类型为:_doc) |
文档(Document)
一个文档是一个可被索引的基础信息单元,也就是一条数据。
比如:你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而JSON 是一个到处存在的互联网数据交互格式。
在一个 index/type 里面,你可以存储任意多的文档。
字段(Field)
相当于是数据表的字段,对文档数据根据不同属性进行的分类标识。
映射(Mapping)
mapping 是处理数据的方式和规则方面做一些限制,如:某个字段的数据类型、默认值、分析器、是否被索引等等。这些都是映射里面可以设置的,其它就是处理ES 里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射, 并且需要思考如何建立映射才能对性能更好。
分片(Shards)
一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有 10 亿文档数据的索引占据 1TB 的磁盘空间,而任一节点都可能没有这样大的磁盘空间。或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch 提供了将索引划分成多份的能力, 每一份就称之为分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点 上。
分片很重要,主要有两方面的原因:
1) 允许你水平分割 / 扩展你的内容容量。
2) 允许你在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量。
至于一个分片怎样分布,它的文档怎样聚合和搜索请求,是完全由 Elasticsearch 管理的, 对于作为用户的你来说,这些都是透明的,无需过分关心。
Kibana
Kibana 是一个免费且开放的用户界面,能够让你对 Elasticsearch 数据进行可视化,并让你在 Elastic Stack 中进行导航。你可以进行各种操作,从跟踪查询负载,到理解请求如何流经你的整个应用,都能轻松完成。
下载地址:https://artifacts.elastic.co/downloads/kibana/kibana-7.8.0-windows-x86_64.zip
1. 解压缩下载的 zip 文件
2. 修改 config/kibana.yml 文件
# 默认端口server.port: 5601 # ES 服务器的地址
elasticsearch.hosts: ["http://localhost:9200"] # 索引名
kibana.index: ".kibana"
# 支持中文
i18n.locale: "zh-CN"
3. Windows 环境下执行 bin/kibana.bat 文件
4. 通过浏览器访问 : http://localhost:5601
took:耗费了几毫秒
2 timed_out:是否超时,false是没有,默认无timeout
3 _shards:shards fail的条件(primary和replica全部挂掉),不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary shard上去,当然了,每个primary shard都可能会有一个或多个replic shard,所以请求也可以到primary shard的其中一个replica shard上去。
4 hits.total:本次搜索,返回了几条结果
5 hits.max_score:score的含义,就是document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高
6 hits.hits:包含了匹配搜索的document的详细数据,默认查询前10条数据,按_score降序排序
KIBANA工具操作ES基本命令
传统HTTP请求与kibana对于es数据库的操作对比
使用postman:PUT请求http://192.168.0.184:9200/book
kibana使用命令:PUT /books
总的来说就是kibana已经指定了es的ip和端口,只需要执行命令即可
索引操作
得到所有的索引
对比关系型数据库,创建索引就等同于创建数据库
GET /_cat/indices
这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉,服务器响应结果如下
表头 | 含义 |
health | 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常) |
status | 索引打开、关闭状态 |
index | 索引名 |
uuid | 索引统一编号 |
pri | 主分片数量 |
rep | 副本数量 |
docs.count | 可用文档数量 |
docs.deleted | 文档删除状态(逻辑删除) |
store.size | 主分片和副分片整体占空间大小 |
pri.store.size | 主分片占空间大小 |
索引创建
PUT /books
{
"acknowledged" : true, //响应结果
"shards_acknowledged" : true,//分配结果
"index" : "books"//索引名
}
单个索引查询
GET /books
删除索引
DELETE /books
文档操作
创建文档
POST /books/_doc
{
"title":"一只特立独行的喵",
"type":"纸书",
"cover":"https://img2.doubanio.com/view/subject/s/public/s1670642.jpg",
"price":25.5
}
返回结果说明:
{
"_index": "shopping",//索引
"_type": "_doc", //类型-文档
"_id": "eWcmhIABKUfPp8KLGjYr",//唯一标识,可以类比为 MySQL 中的主键,随机生成也可指定
"_version": 1,//版本
"result": "created",//结果,这里的 create 表示创建成功
"_shards": {//
"total": 2,//分片 - 总数
"successful": 1,//分片 - 总数
"failed": 0//分片 - 总数
},
"_seq_no": 0,
"_primary_term": 1
}
Dynamic mapping 动态映射的说明
上一步的创建文档中,我们并未创建索引的mapping,类似于并未创建mysql中的数据表结构,但是仍然可以将数据存入数据库中。此处在官方文档的解释如下,简单来说就是es的Dynamic mapping机制允许用户在为建立mapping时,根据新增文档的字段和数据类型动态的添加新字段
动态映射允许您在刚刚开始时对数据进行实验和探索。通过索引文档,Elasticsearch 自动添加新字段。您可以向顶级映射、内部对象和嵌套字段添加字段。
使用动态模板定义应用于根据匹配条件动态添加字段的自定义映射。
指定id创建文档
POST /books/_doc/10001
{
"title":"三体一:地球往事",
"type":"电子书",
"cover":"https://img2.doubanio.com/view/subject/s/public/s1670642.jpg",
"price":100
}
主键查询
GET /books/_doc/10001
GET方式全查询
GET /books/_doc/_search (弃用)
GET /books/_search (推荐 )
POST方式全查询(推荐)
POST /books/_search
{
"query":{
"match_all":{
}
}
}
全量修改
POST /books/_doc/10001
{
"title":"三体一:地球往事2",
"type":"电子书",
"cover":"https://img2.doubanio.com/view/subject/s/public/s1670642.jpg",
"price":100
}
局部修改
POST /books/_update/10001
{
"doc": {
"title":"三体一:地球往事-局部修改"
}
}
数据删除
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
DELETE /books/_doc/7Si7doEB0tY96fCAXtcd
条件查询
首先增加多条数据记录来作为查询数据
请求带参数查询(不推荐)
如果包含中文参数会出现乱码情况,而且暴露出来参数方式容易被攻击,类似于redis的缓存击穿问题
请求体带参查询
match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系
POST /books/_search
{
"query": {
"match": {
"price":100
}
}
}
全量查询并且指定字段返回
{
"query": {
"match_all": {
}
},
"_source":["title"]
}
分页查询
from - 跳过多少条数据 【计算】
size - 每页展示多少条数据
POST /books/_search
{
"query": {
"match_all": {
}
},
"from": 0,
"size": 2
}
排序查询
POST /books/_search
{
"query": {
"match_all": {
}
},
"sort": [
{
"price": { #价格降序排序
"order": "desc"
}
}
]
}
多条件查询
`bool`把各种其它查询通过`must`(必须 )、`must_not`(必须不)、`should`(应该【or】)的方式进行组合
查询电子书并且价格为100的
POST /books/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"type": "电子书"
}
},{
"match": {
"price": "100"
}
}
]
}
}
}
多条件范围查询
查询电子书并且价格为100的
POST /books/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"type": "纸书"
}
},
{
"match": {
"type": "电子书"
}
}
],
"filter": {
"range": {
"price": {
"gte": 100
}
}
}
}
}
}
全文检索
这功能像搜索引擎那样,如title输入“三体球”,返回结果带回title有“三体”和“球”的。
POST /books/_search
{
"query": {
"match": {
"title":"三体球"
}
}
}
完全匹配检索
POST /books/_search
{
"query": {
"match_phrase": {
"title":"球状闪电"
}
}
}
模糊查询
高亮查询
对title中的“三体”字段高亮展示
POST /books/_search
{
"query": {
"match": {
"title":"三体"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
指定高亮标签查询
对title中的“三体”字段高亮展示
{
"query": {
"match_phrase": {
"title": "三体"
}
},
"highlight": {
"pre_tags": [ #前缀
"<tag1>"
],
"post_tags": [ #后缀
"</tag1>"
],
"fields": {
"title": {} #高亮字段
}
}
}
聚合查询
聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by,当然还有很多其他的聚合,例如取最大值max、平均值avg等等。
{
"size":0,//如果加上这段会去除查询出来的原始数据
"aggs":{//聚合操作
"price_group":{//名称,自定义
"terms":{ //分组
"field":"price"//分组字段
}
}
}
}
平均值
POST /books/_search
{
"size":0,
"aggs":{
"price_avg":{
"avg":{
"field":"price"
}
}
}
}
映射关系(mapping)
Elasticsearch是面向文档型数据库,每条数据记录就是一个文档。与关系型数据库 MySQL 存储数据类比,ES 里的 Index 可以看做一个库,而 Types 相当于表, Documents 则相当于表的行。
需要注意的是这里 Types 的概念已经被逐渐弱化, Elasticsearch 6.X 中,一个 index 下已经只能包含一个type, Elasticsearch 7.X 中, Type 的概念已经被删除了。
Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据对比关系图
由类比可知,建立了索引后就相当于mysql中的database建立,那么建立索引库(index)中的映射就是相当于mysql中建立数据库表结构
建立数据库表需要设置字段的名称,类型,长度,约束等。
建立索引库也需要知道该索引下有哪些字段类型以及字段的约束信息,这就叫做映射(mapping)。
创建用户索引
创建映射
用户索引下增加name, sex, tel三个字段
PUT /user/_mapping
{
"properties":{
"name":{
"type":"text",
"index":true
},
"sex":{
"type":"keyword",
"index":false
},
"tel":{
"type":"keyword",
"index":false
}
}
}
- 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
- type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的
- String 类型,又分两种:
- text:可分词
- String 类型,又分两种:
-
-
- keyword:不可分词,数据会作为完整字段进行匹配
-
-
- Numerical:数值类型,分两类
- 基本数据类型:long、integer、short、byte、double、float、half_float
- Numerical:数值类型,分两类
-
-
- 浮点数的高精度类型:scaled_float
-
-
- Date:日期类型
-
- Array:数组类型
-
- Object:对象
- index:是否索引,默认为true,也就是说你不进行任何配置,所有字段都会被索引。
- true:字段会被索引,则可以用来进行搜索
-
- false:字段不会被索引,不能用来搜索
- store:是否将数据进行独立存储,默认为 false
- 原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
- analyzer:分词器,这里的ik_max_word 即使用 ik 分词器,后面会有专门的章节学习
查询映射
GET /user/_mapping
新增文档数据
PUT /user/_doc/101
{
"name":"周全",
"sex":"男生",
"tel":"15423659874"
}
数据查询
1.查询name包含"周"的数据
注意:此时的name字段的type为text,而不是keyword
POST /user/_search
{
"query": {
"match": {
"name": "周"
}
}
}
2.查询sex包含"男"的数据
由于创建映射时,“sex”的类型设置为了“keyword”,因此必须在完全匹配时才能得出匹配数据
完全匹配:
3.查询电话数据
查询失败原因:创建映射时,tel的“index”设置为了false(默认是true),因此不参与检索
"reason" : "failed to create query: Cannot search on field [tel] since it is not indexed."
映射type字段text与keyword的区别
1.官方文档对于_mapping 的说明
Explicit mapping 显式映射
Explicit mapping allows you to precisely choose how to define the mapping definition, such as:
显式映射允许您精确地选择如何定义映射定义,例如:
1、Which string fields should be treated as full text fields.
应将哪些字符串字段视为全文字段
2、Which fields contain numbers, dates, or geolocations.
哪些字段包含数字、日期或地理位置
3、The format of date values. 日期值
4、Custom rules to control the mapping for dynamically added fields
控制映射的自定义规则动态添加字段.
2.官方文档对于keyword的说明
The keyword family includes the following field types:
keyword, which is used for structured content such as IDs, email addresses, hostnames, status codes, zip codes, or tags.
constant_keyword for keyword fields that always contain the same value.
wildcard for unstructured machine-generated content. The wildcard type is optimized for fields with large values or high cardinality.
大致含义:就是keyword这是用于结构化内容,如 id,电子邮件地址,主机名,对于总是包含相同值的关键字字段。
Keyword fields are often used in sorting, aggregations, and term-level queries, such as term. Avoid using keyword fields for full-text search. Use the text field type instead.
关键字字段通常用于排序、聚合和术语级查询(如 term)。避免在全文搜索中使用关键字字段。改为使用文本字段类型。
3.官方文档对于text的说明
(1) 文本系列包含字段类型
The text family includes the following field types:
- text, the traditional field type for full-text content such as the body of an email or the description of a product.
- match_only_text, a space-optimized variant of text that disables scoring and performs slower on queries that need positions. It is best suited for indexing log messages.
大意:text,传统的字段类型为全文内容,例如电子邮件正文或产品说明
(2) Text field type 文本字段类型
A field to index full-text values, such as the body of an email or the description of a product. These fields are analyzed, that is they are passed through an analyzer to convert the string into a list of individual terms before being indexed. The analysis process allows Elasticsearch to search for individual words within each full text field. Text fields are not used for sorting and seldom used for aggregations (although the significant text aggregation is a notable exception).
索引全文值的字段,如电子邮件正文或产品说明。对这些字段进行分析,即在进行索引之前通过分析器将字符串转换为单个术语的列表。分析过程允许 Elasticsearch 在每个全文字段中搜索单独的单词。文本字段不用于排序,也很少用于聚合(尽管重要的文本聚合是一个明显的例外)。
text fields are best suited for unstructured but human-readable content. If you need to index unstructured machine-generated content, see Mapping unstructured content.
文本字段最适合非结构化但可读的内容。如果需要索引非结构化机器生成的内容,请参见映射非结构化内容。
If you need to index structured content such as email addresses, hostnames, status codes, or tags, it is likely that you should rather use a keyword field.
如果你需要索引电子邮件地址、主机名、状态代码或标签等结构化内容,你可能更应该使用关键字字段。
text与keyword总结
keyword主要用于结构化内容的字段,并且总是会有相同值的字段。因为通常需要用于聚合、排序和术语级查询(如 term),所以避免参与全文检索
text字段类型用于全文内容,例如电子邮件正文或产品说明,并且es会通过分析器对字符串进行分词,可以在全文检索中搜索单独的单词。文本字段最适合非结构化但可读的内容并且不用于排序,也很少用于聚合
IK 分词器
概述
Elaticsearch在保存数据时,会根据创建索引的mapping映射对于每个字段的数据进行分词。同时在查询索引数据的时候会对于检索词进行分词,然后再检索。因此分词对于数据库的查询效率和相关度的关系是非常大的。
分词器的作用
ES在创建索引和查询索引的时候都需要需要用到分词器进行分词,而分词器的作用:
分词器的作用是把一段文本中的词按照一定规则进行切分
由于检索和分词都需要用到分词器,因此务必保证使用的一致性,否则由于分词规则的不同导致检索不出来结果
因为分词器对应的是Analyzer类,这是一个抽象类,切分词的具体规则是由子类实现的。
也就是说不同的分词器分词的规则是不同的!
分词器的操作分析
标准分词器模式
使用kibana执行dsl语句测试
#测试分词器
POST /_analyze
{
"analyzer": "ik_smart",
"text":"学习Elasticsearch数据库"
}
分词结果:
{
"tokens" : [
{
"token" : "学",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<IDEOGRAPHIC>",
"position" : 0
},
{
"token" : "习",
"start_offset" : 1,
"end_offset" : 2,
"type" : "<IDEOGRAPHIC>",
"position" : 1
},
{
"token" : "elasticsearch",
"start_offset" : 2,
"end_offset" : 15,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "数",
"start_offset" : 15,
"end_offset" : 16,
"type" : "<IDEOGRAPHIC>",
"position" : 3
},
{
"token" : "据",
"start_offset" : 16,
"end_offset" : 17,
"type" : "<IDEOGRAPHIC>",
"position" : 4
},
{
"token" : "库",
"start_offset" : 17,
"end_offset" : 18,
"type" : "<IDEOGRAPHIC>",
"position" : 5
}
]
}
由结果可见,标准分词器模式对于中文的分词并不友好,因此需要使用ik分词器
ik分词器
我 们 这 里 采 用 IK 中 文 分 词 器 , 下 载 地 址 为 : https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.8.0
将解压后的后的文件夹放入 ES 根目录下的 plugins 目录下,重启ES 即可使用。
ik_smart:最少切分(最粗粒度的切分模式)
#测试分词器
POST /_analyze
{
"analyzer": "ik_smart",
"text":"学习Elasticsearch数据库"
}
分词结果:
ik_max_word:最多切分(最细粒度的切分模式)
#测试分词器
POST /_analyze
{
"analyzer": "ik_max_word",
"text":"学习Elasticsearch数据库"
}
分词结果:
分词的扩展
在数据库安装目录/plugins/elasticsearch-analysis-ik-7.8.0/config/目录下存在配置文件IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
新增扩展字典
首先查看未扩展之前的检索
在配置文件同目录下新增扩展词典:myext.dict
重启es数据库,可以看到加载了自定义的扩展分词
重新执行分词语句,可以看到作为一个‘奥利给’词语被切分
新增扩展停止词字典
停止词的概念:
有些词在文本中出现的频率非常高,但是对文本所携带的信息基本不产生影响。文本经过分词之后,停止词通常被过滤掉,不会被进行索引。
在检索的时候,用户的查询中如果含有停止词,检索系统在分词处理会将其过滤掉。
例如:
英文停用词:a、an、the、of等
中文停用词:的、了、着、是、标点符号等
停止词的作用
排除停用词可以加快建立索引的速度,减小索引库文件的大小,并且还可以提高查询的准确度。
停止词的操作测试
在配置文件同级目录下增加停止词配置
重启es数据库,可以看到加载了自定义的扩展分词
切分中已经去除了停止词
使用中文分词后的结果为:
{
"tokens": [{
"token": " 测 试 ",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": " 单 词 ",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
}
]
}
ES 中也可以进行扩展词汇,首先查询
# GET http://localhost:9200/_analyze
{
"text":" 弗 雷 尔 卓 德 ", "analyzer":"ik_max_word"
}
仅仅可以得到每个字的分词结果,我们需要做的就是使分词器识别到弗雷尔卓德也是一个词语
{
"tokens": [{
"token": " 弗 ",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": " 雷 ",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": " 尔 ",
"start_offset": 2,
"end_offset": 3,
"type": "CN_CHAR",
"position": 2
},
{
"token": " 卓 ",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 3
},
{
"token": " 德 ",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 4
}
]
}
首先进入 ES 根目录中的 plugins 文件夹下的 ik 文件夹,进入 config 目录,创建 custom.dic 文件,写入弗雷尔卓德。同时打开 IKAnalyzer.cfg.xml 文件,将新建的 custom.dic 配置其中, 重启ES 服务器。