一、环境准备
1. ES安装
建议直接用docker。
# 安装ElasticSearch
docker pull elasticsearch:7.17.6
# 安装Kibana
docker pull kibana:7.17.6
# 查看已安装镜像
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
elasticsearch 7.17.6 5fad10241ffd 2 months ago 606MB
kibana 7.17.6 4239c3f5bd3d 2 months ago 799MB
# 启动ElasticSearch
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name MyEs7 5fad10241ffd
# 启动Kibana
docker run -d -p 5601:5601 --name kb7 --link MyEs7:elasticsearch 4239c3f5bd3d
# 查看容器启动状态
docker ps
# 浏览器访问Kibana
http://localhost:5601/
# 如果用Chrome的ElasitcSearch Head 插件,则直接访问访问 ES地址
http://localhost:9200/
docker启动参数说明:
- -d 后台启动
- -p 9200:9200 将虚拟机9200端口映射到elasticsearch的9200端口(web通信默认使用9200端口)
- -p 9300:9300 将虚拟机9300端口映射到elasticsearch的9300端口(分布式情况下,各个节点之间通信默认使用9300端口)
- –name MyEs7 指定一个名字(MyEs 随意指定)
可用 ElasticSearch Head替代kibana:
不用kibana的话,也可以在chrome浏览器的插件中搜索 ElasticSearch Head安装。
二、基本概念
2.1 节点(Node)
一个 ES 节点就是一个运行的 ES 实例,可以实现数据存储并且搜索的功能。每个节点都有一个唯一的名称作为身份标识,如果没有设置名称,默认使用 UUID 作为名称。最好给每个节点都定义上有意义的名称,在集群中区分出各个节点。节点通过为其配置的ES集群名称确定其所要加入的集群。
一个机器可以有多个实例(这种情况,机器的cpu core怎么分配给每个实例使用可通过参数配置,默认是每个实例线程池共用机器资源),所以并不能说一台机器就是一个 node,大多数情况下每个 node 运行在一个独立的环境或虚拟机上。
节点有以下几种类型:
Master-eligible nodes与 Master node
每个节点启动后,默认就是一个Master eligible节点,可以通过设置node.master:false来改变,Master-eligible节点可以参加选主流程,成为Master节点,每个节点都保存了集群的状态,但只有Master节点才能修改集群的状态信息,主节点主要负责集群方面的轻量级的动作,比如:创建或删除索引,跟踪集群中的节点,决定分片分配到哪一个节点,在集群再平衡的过程中,如何在节点间移动数据等。
Data Node
可以保存数据的节点,叫做Data Node。负责保存分片数据。在数据扩展上起到了至关重要的作用,每个节点启动后,默认就是一个Data Node节点,可以通过设置node.data:false来改变。
Ingest Node
可以在文档建立索引之前设置一些ingest pipeline的预处理逻辑,来丰富和转换文档。每个节点默认启动就是Ingest Node,可用通过node.ingest:false来禁用。
Coordinating Node
Coordinating Node负责接收Client的请求,将请求分发到合适的节点,最终把结果汇集到一起,每个节点默认都起到了 Coordinating Node的职责,当然如果把Master、Data、Ingest全部禁用,那这个节点就仅是Coordinating Node节点了。
Machine Learning Node
用于机器学习处理的节点。
2.2 集群(cluster)
ES可以作为一个独立的单个搜索服务器。不过,一般为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。
2.3 分片(Shard)
ES的“分片(shard)”机制可将一个索引内部的数据分布地存储于多个节点,它通过将一个索引切分为多个底层物理的Lucene索引完成索引数据的分割存储功能,这每一个物理的Lucene索引称为一个分片(shard)。
一个ES的index由多个shard组成,每个shard承载index的一部分数据。
这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。降低单服务器的压力,构成分布式搜索,提高整体检索的效率(分片数的最优值与硬件参数和数据量大小有关)。分片的数量只能在索引创建前指定,并且索引创建后不能更改。
在搜索时,每个分片都需要搜索一次, 然后 ES 会合并来自所有分片的结果。例如,你要搜索 10 个 index,每个 index 有 5 个分片,那么协调这次搜索的节点就需要合并 5×10=50 个分片的结果。这也是一个你需要注意的地方:如果有太多分片的结果需要合并,或者你发起了一个结果巨大的搜索请求,合并任务会需要大量 CPU 和内存资源。这是第二个让 index 少一些的理由。
2.4 副本(Replica)
副本是一个分片的精确复制,每个分片可以有零个或多个副本。副本的作用:
一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。
二是提高es的查询效率,es会自动对搜索请求进行负载均衡。对于查询压力较大的index,可以考虑提高副本数(number_of_replicas),通过多个副本均摊查询压力
- 一个索引包含一个或多个分片,7.0版本之后默认1个主分片(之前是默认5个),副本可以在索引创建之后修改数量,但主分片数量一旦确定不可修改,只能创建索引
- 每个分片都是一个Lucene实例,有完整的创建索引和处理请求的能力
- ES会自动在nodes上做分片均衡【当我们添加了新的副本文件,会将每个节点数据尽量均匀分配,提高每个节点性能】
- 一个doc不可能同时存在多个主分片中,但每个主分片的副本数量不为一时,可以同时存在多个副本中
- 每个主分片及其副本分片不能同时存在于同一个节点上,最低的可用配置是两个节点互为主备
2.5 分片和副本数选择
shard数量(number_of_shards)设置过多或过低都会引发一些问题:shard数量过多,则批量写入/查询请求被分割为过多的子写入/查询,导致该index的写入、查询拒绝率上升;对于数据量较大的inex,当其shard数量过小时,无法充分利用节点资源,造成机器资源利用率不高 或 不均衡,影响写入/查询的效率。
对于每个index的shard数量,可以根据数据总量、写入压力、节点数量等综合考量后设定,然后根据数据增长状态定期检测下shard数量是否合理。腾讯云CES技术团队的推荐方案是:
- 对于数据量较小(100GB以下)的index,往往写入压力查询压力相对较低,一般设置3~5个shard,number_of_replicas设置为1即可(也就是一主一从,共两副本) 。
- 对于数据量较大(100GB以上)的index: 一般把单个shard的数据量控制在(20GB~50GB) 让index压力分摊至多个节点:可通过index.routing.allocation.total_shards_per_node参数,强制限定一个节点上该index的shard数量,让shard尽量分配到不同节点上 综合考虑整个index的shard数量,如果shard数量(不包括副本)超过50个,就很可能引发拒绝率上升的问题,此时可考虑把该index拆分为多个独立的index,分摊数据量,同时配合routing使用,降低每个查询需要访问的shard数量。
2.6 ES的数据架构
1)索引(index)
ES将数据存储于一个或多个索引中,索引是具有类似特性的文档的集合。类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库。
一个ES集群中可以按需创建任意数目的索引,但根据不同的硬件配置,索引数有一个建议范围(这个知识点我们以后进行详细讲解)。
2)类型(Type)
类型是索引内部的逻辑分区(category/partition),一般来说,类型就是为那些拥有相同的域的文档做的预定义。类比传统的关系型数据库领域来说,类型相当于“表”。
使用 type 允许我们在一个 index 里存储多种类型的数据,这样就可以减少 index 的数量了。在使用时,向每个文档加入 _type 字段,在指定 type 搜索时就会被用于过滤。使用 type 的一个好处是,搜索一个 index 下的多个 type,和只搜索一个 type 相比没有额外的开销 —— 需要合并结果的分片数量是一样的。
特别注意:
6.x版本:Removal of types,在 6.0 里面,开始不支持一个 index 里面存在多个 type
7.x版本: 正式废除单个索引下多 Type 的支持(只有_doc这一个默认type)
3)文档(Document)
文档是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,基于JSON格式进行表示。文档由一个或多个域组成,每个域拥有一个名字及一个或多个值,有多个值的域通常称为“多值域”。每个文档可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。相当于mysql表中的row。
文档的原始信息都存放在_source字段中,获取文档信息:
GET es_test/_doc/1 #获取文档_source和metadata
GET es_test/_source/1 #仅获取_source
GET es_test/_doc/2?_source_include=title,content # 获取metadata和指定_source字段信息,7.x以上用_source_includes,多个s
GET es_test/_source/2?_source_include=title,author # 获取指定_source字段信息,7.x以上用_source_includes,多个s
GET es_test/_doc/1?stored_fields=title,content # 获取stored字段信息
# 获取多个_id文档
GET es_test/_search
{
"query": {
"ids": {
"values": [1,2,3]
# "_source": false #可关闭获取_source内容,只返回meta内容
}
}
}
4)映射(Mapping)
映射是定义文档及其包含的字段如何存储和索引的过程。
PUT /es_test?pretty
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0
}
},
"mappings": {
"_doc": {
"dynamic": true,
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "text"
},
"content": {
"type": "text"
},
"tags": {
"type": "keyword"
}
}
}
}
}
三、数据类型
到8.x版本,es支持的数据类型已有29种,可查阅官方文档:数据类型。本章节介绍一下核心数据类型(core-data types)。
核心数据类型:
- String 类型
- text
- token_count
- keyword
- constant_keyword
- wildcard
- 数值类型
- 整型
- float
- double
- half_float
- scaled_float
- 浮点型
- byte
- short
- integer
- long
- unsigned_long
- 整型
- 时间类型
- date
- 复杂类型
- (array)
- object
- flattend
- nested
- join
- 特定类型
- GEO地理类
- geo_point
- geo_shape
- point
- shape
- GEO地理类
- 文档排序类
- dense_vector
- rank_feature
- rank_features
3.1 关于settings和mapping
一个索引的schema和特征是通过settings以及mapping设定的,在第二章已经见过。
# 定义es_test的相信息
PUT es_test
{
"settings": {
...
},
"mappings": {
"_doc": {
"properties": {
... #指定字段名和类型
}
}
}
}
3.1.1 动态mapping(Dynamic Mapping)
更详细的可参考:Elasticsearch - mappings之dynamic的三种状态
es自动生成字段和类型的方式,两种情况:
- 未定义mapping,就创建索引
- 定义了mapping,未包含新字段,增加新字段。
ES自动推断类型的规则:
3.1.2 显示mapping(Explicit Mapping)
ES提供两种用于maping的操作:
-
PUT index
创建阶段,提供全量字段信息。 -
PUT index/_mapping
,使用阶段,可add新字段,仅需提供add部分字段信息即可。注意,不可以修改已定义字段类型。
若想修改字段类型,可用re_index,先定义好新索引各字段类型,创建新索引。将旧索引copy过去。
POST _reindex
{
"source": {"index": "orders"},
"dest": {"index": "orders_new"}
}
3.1.3 自动类型转换(type coercion)
当定义的类型和输入的类型不一致时,es能自动做类型转换,当转换不了时,数据不能写入。例如:
"age":{"type":"short"}
PUT cars/_doc/1
{
"age":"23" # 字符串"23"自动转换成 23,如果是"age":"st" 则无法转换,该条数据不能插入,并给出错误提示
}
搜索时,同样会发生这种转换。
比较特别的:当boolean类型提供空字符串时,会转换成false
:"blockbuster":""
。
3.2 关于分词
Analysis:即文本分析,是把全文本转化为一系列单词(term/token)的过程,也叫分词;在Elasticsearch 中可通过内置分词器实现分词,也可以按需定制分词器。为了和tokenizer分词器区分开来,本文把Analyzer 叫分析器。
分词 | 内容 |
---|---|
不分词(Before Tokenization) | Covid changed our lives. It changed the way we work. |
分词后(After Tokenization) | [Covid,changed,our,lives,it,changed,the,way,we,work] |
3.2.1 Analyzer 由三部分组成
- Character Filters:原始文本处理,如去除 html
- Tokenizer:按照规则切分为单词
- Token Filters:对切分单词加工、转换大小写、删除 stopwords,增加同义词
官方介绍:
1)字符过滤器 character filter
首先,字符串按顺序通过每个字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and。
2)分词器 tokenizer
其次,字符串被 分词器 分为单个的词条。一个 whitespace的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
3)词条过滤器token filter
最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条,例如,lowercase token filter 小写化(将ES转为es)、stop token filter 删除词条(例如, 像 a, and, the 等无用词),或者synonym token filter 增加词条(例如,像 jump 和 leap 这种同义词)。
默认分析器为标准分析器。由以下三个部分组成:(注意:带有lowercase),所以用term语法去搜标准分析器分词的字段时注意先人工转成小写,用match语法搜则不用担心,因为match会先经过同样的分析器,再搜索。
扩展:三部分可选参数列表
3.2.2 自定义分析器
#1、定义名为“custom_analyzer”的自定义分析器:大写转为小写
PUT es_test
{
"settings": {
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
}
}
},
# 2、该字段my_text使用custom_analyzer分析器
"mappings": {
"_doc": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "custom_analyzer"
}
}
}
}
}
3.2.4 分析器
分析器使用的三个情形:
1,Index time analysis. 创建或者更新文档时,会对文档进行分词
2,Search time analysis. 查询时,对查询语句分词
3, _analyze接口
ES内置了很多Analyzer, 还有很多第三方的Analyzer插件, 比如一些处理中文的Analyzer(中文分词)。
analyzer、 tokenizer、 filter可以在elasticsearch.yml 配置。
场景分析器:
analyzer | logical name | description |
---|---|---|
standard analyzer | standard | standard tokenizer, standard filter, lower case filter, stop filter |
simple analyzer | simple | lower case tokenizer |
stop analyzer | stop | lower case tokenizer, stop filter |
keyword analyzer | keyword | 不分词,内容整体作为一个token(not_analyzed) |
pattern analyzer | whitespace | 正则表达式分词,默认匹配\W+ |
language analyzers | lang | 各种语言 |
snowball analyzer | snowball | standard tokenizer, standard filter, lower case filter, stop filter, snowball filter |
custom analyzer | custom | 一个Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter |
- 查询时通过analyzer指定分析器
POST test_index/_search
{
"query": {
"match": {
"name": {
"query": "lin",
"analyzer": "standard"
}
}
}
}
- 创建index mapping时指定search_analyzer
PUT test_index
{
"mappings": {
"doc": {
"properties": {
"title":{
"type": "text",
"analyzer": "whitespace", # 指定生成倒排索引的分析器
"search_analyzer": "standard" # 指定搜索该字段的分析器
}
}
}
}
}
索引时分词是通过配置 Index mapping中的每个字段的参数analyzer指定的。
ES使用分析器的顺序
ElasticSearch确定生成索引时的 analyzer:
1)读取字段的“analyzer”配置
2)上述步骤没有,再读取index的setting:analysis.analyzer.default
3)都没有,使用默认的 standard 标准分析器
# 1)读取字段的“analyzer”配置
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace"
}
}
}
}
# 2)上述步骤没有,再读取index的setting:analysis.analyzer.default
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "english"
}
}
}
}
}
ElasticSearch确定搜索时的 search_analyzer:
1)search API 指定 analyzer
2)读取 index 的 mapping 字段配置 search_analyzer
3)读取 index 的 setting 的 analysis.analyzer.default_search
4)field 的 analyzer
5)都没有,使用默认的 standard analyzer
# 1) search API 指定 analyzer
GET my_index/_search
{
"query": {
"match": {
"message": {
"query": "Quick foxes",
"analyzer": "stop"
}
}
}
}
# 2) 读取 index 的 mapping 字段配置 search_analyzer
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace",
"search_analyzer": "simple"
}
}
}
}
# 3) 读取 index 的 setting 的 analysis.analyzer.default_search
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "simple"
},
"default_search": {
"type": "whitespace"
}
}
}
}
}
3.2.5 粗粒度和细粒度分词
中文分析器有粗粒度和细粒度分析器,以ik分析器为例:
分析器 | 说明 | 语句 | 分词 | 适用场景 |
---|---|---|---|---|
ik_max_word | 细颗粒度分词 | 关注我系统学习ES | [关注,我,系统学,系统,学习,es] | 穷尽所有分词可能,适合 Term 查询 |
ik_smart | 粗粒度分词 | 关注我系统学习ES | [关注,我,系统,学习,es] | 适合 Phrase 查询 |
3.2.6 关于normalizer
需要分词的字符串通常是text类型。而es中还有一种不需要分词的string类型,叫做keyword。keyword类型的整个句子可以类似于text类型分词后的一个词条。
对于keyword的处理,通常是定义normalizer,这是专门为keyword类型存在的。他和text类型的analyzer的区别是,没有tokenizer这一步:
- Character Filters:原始文本处理,如去除 html
- Token Filters:对切分单词加工、小写、删除 stopwords,增加同义词
PUT es_test
{
"settings": {
"analysis": {
"normalizer": {
"my_normalizer": {
"type": "custom",
"char_filter": [],
"filter": ["lowercase", "asciifolding"]
}
}
}
},
"mappings": {
"properties": {
"foo": {
"type": "keyword",
"normalizer": "my_normalizer"
}
}
}
}
3.3 倒排索引
倒排索引是 Elasticsearch 中非常重要的索引结构,是从文档单词到文档 ID 的映射过程。
假设有两篇文章:
倒排索引就是建立词和文章id间的关系,通过词能够找到文章。简单例子如下:
倒排序索引包含两个部分:
-
单词词典:记录所有文档单词,记录单词到倒排列表的关联关系
-
倒排列表:记录单词与对应文档结合,由倒排索引项组成
倒排索引项:
-
文档
-
词频 TF - 单词在文档中出现的次数,用于相关性评分
-
位置(Position)- 单词在文档中分词的位置,用于phrase query
-
偏移(Offset)- 记录单词开始结束的位置,实现高亮显示
以 Token“学习”为例(这才是全部的倒排索引信息):
3.4 String 类型
1)text——会分词
我们不去特殊定义它的分析器,那么ES就会使用默认的分析器 standard。调用分析器分析的命令:
GET /_analyze
{
"text": ["my name is A"],
"analyzer": "standard" # "analyzer": "keyword" 则返回不分词结果
}
2) token_count——记录分词数
可记录filed分词后长度。
PUT tech_books
{
"mappings": {
"properties": {
"title": { # 父field
"type": "text",
"fields": {
"word_count": { # 通常放到下一层,用子field来记录
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
}
GET tech_books/_search
{
"query": {
"term": {
"title.word_count": { # <outer_field>.<inner_field> 的方式获取
"value": 4
}
}
}
}
3)keyword——不会分词
term查询是查不分词结果
4)constant_keyword
当某个字段需要用一个不变的keyword的时候。
PUT census
{
"mappings": {
"properties": {
"country":{
"type": "constant_keyword",
"value":"United Kingdom" #该索引country字段都为United Kingdom
}
}
}
}
5) wildcard
wildcard也是keyword家族的。在mapping定义时指定为wildcard type则可在搜索时,对该字段进行wildcard搜索。
GET errors/_search
{
"query": {
"wildcard": {
"description": {
"value": "*obj*"
}
}
}
}
3.5 数值类型
主要是注意各类型的范围。
3.6 date 时间类型
date类型允许我们规定格式,如果不指定格式,储存的格式,ES是可以自动控制的(但仅限于三种)。
注意:一旦我们自行规定了格式,如果新增数据不符合这个格式,ES将会报错mapper_parsing_exception。
可以使用的格式有:
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd
epoch_millis(时间戳-毫秒)
epoch_second(时间戳-秒)
# 规定格式如下:|| 表示或者
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis|dd-MM-yy||dd/MM/yyyy|||yyyy/MM/dd" # 支持用yyyy,MM,dd, HH,mm ss自定义
}
}
}
}
}
3.7 复杂类型
ES的复杂类型有3个,array、object、nested。
1)array:在Elasticsearch中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值都必须具有相同的数据类型。
# 创建索引
PUT /toherotest
{
"mappings": {
"_doc":{
"properties" : {
"field1" : { "type" : "text" }
}
}
}
}
# 存入数据
POST /toherotest/_doc/1
{
"field1":"中国我爱你"
}
# 新增数据-array
POST /toherotest/_doc/2
{
"field1":["这是","一个","数组"] #注意,直接用的是field1
}
2)object就是一个json提;需要注意的是,object类型的字段,也可以有多个值,形成Array<object>
的数据结构。
重点:Array<object>
中的object不允许彼此独立地索引查询。这是什么意思呢?举个简单例子:我们现在有2条数据:数据结构都是一个Array<object>
:
第一条数据:[ { "name":"tohero1", "age":1 }, { "name":"tohero2", "age":2 } ]
第二条数据:[ { "name":"tohero1", "age":2 }, { "name":"tohero2", "age":1 } ]
如果此时我们的需求是,只要 name = “tohero1”and “age”= 1
的数据,但没法查,两条数据都会查出来。怎么实现?用nessted类型。
3)nested 类型
需要建立对象数组的索引并保持数组中每个对象的独立性,则应使用nested数据类型而不是 object数据类型。在内部,嵌套对象索引阵列作为一个单独的隐藏文档中的每个对象,这意味着每个嵌套的对象可以被独立的查询。
三、GEO 地理位置类型
对于 GEO 地理位置类型,分为 地图:Geo-point 和 形状 :Geo-shape,两种数据类型。
对于web开发,一般常用的是 地图类型 Geo-point。
知道如何定义,如何查询即可
四、查询(queries)
查询方式有两种:
- 基于URI请求的查询,如:
GET movies/_search?q=title:Godfather
可获取索引movies中title匹配Godfather 的文档。 - 基于query-DSL的查询:domain-specific language(DSL)在ES中是基于json结构体的,示例如下:
GET movies/_search
{
"query": {
"match": {
"title": "Godfather"
}
}
}
实际应用中,DSL是主流。
GET|POST <your_index_name>/_search?q=<name:value> AND|OR <name:value>
GET movies/_search?q=title:Godfather Knight Shawshank # 支持value包含多个值
GET movies/_search?q=title:Knight AND actors:Bale # AND语句使用
GET movies/_search?q=title:Godfather actors:Bale # 默认为OR
GET movies/_search?q=title:Godfather actors:Bale&default_operator=AND #修改默认
GET movies/_search?q=title:Godfather actors:(Brando OR Pacino) rating:(>=9.0 AND <=9.5)&from=0&size=10&explain=true&sort=rating&default_operator=AND # 更多参数
#DSL在curl中的使用
curl -XGET "http://localhost:9200/movies/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"multi_match": {
"query": "Lord",
"fields": ["synopsis","title"]
}
}
}'
查询的两种内部结构(context):
ES将所有查询自动分为两类:
- query context:会计算相关分,返回结果会返回这个分数。
- filter context:不计算相关分,返回结果中没有相关分,可大幅提高搜索效率。三种情况放在filter context中执行:
- bool 的filter语句
- bool 的must_not语句
- contant_score 的filter语句
常用查询参数:
查询蚕食是指和query同级的参数:
size:每页获取的文档数量,默认10000,受_settings中的max_result_window参数控制。
from:起始页数,默认0
highlight:高亮匹配到的字段
explain:见常用接口章节的"_explain"接口
sort:排序依据,不指定的话,按相关性分数"_score"排
_source:是否打印_source字段,见接口章节
fields:"_source"为false时,打印_source中指定字段。
scirpt_fields:自定义的脚本字段
indices_boost:调整夸索引搜索时,不同索引的权重
GET movies*/_search
{
"query": { ... },
"size":10,
"from":3,# 跳过前2页,即跳过了2*10个结果
"highlight": {
"fields": {
"field1": {}, #指定要高亮的字段
"field2": {}
},
"pre_tags": "符号1", #自定义高亮标识符 默认是"<em>"
"post_tags": "符号2",#自定义高亮标识符 默认是"</em>"
},
"sort": [
{ "field1" :{ "order": "desc" } }, #注意field也可以是metadata中字段,如_score
{ "field2" :{ "order": "desc" } } # 多个字段是,当filed1一样时,才按field2排序
],
"_source": ["title*","synopsis", "rating"], # 注意字段名可通配符匹配
"script_fields": {
"top_rated_movie": {
"script": {
"lang": "painless",
"source": "if (doc['rating'].value > 9.0) 'true'; else 'false'"
}
}
},# 返回结果中会显示"top_rated_movie":“true”
"indices_boost": [
{ "movies": 0.1},
{ "movies_new": 0},
{ "movies_top": 2.0}
]
}
索引名和字段名都支持通配符匹配,通配符会匹配到子字段,如title*
会匹配到title
和title.original
。
查询可分为三类:
- term-level queries
- full-text queries
- compound queries
es的数据分为结构化数据(structured data(non-text data))和非结构化数据(unstructured data (fulltext-data))。
Numbers, dates, range, IP等都是结构化数据。
term-level queries专门用于结构化数据查询。
非结构化数据 (fulltext)的查询和索引都可经过analyzer。
4.1 term-level 查询
term-level 查询的查询是不关心query和内容的相关程度的,所以term-level 查询不关注相关性分。注意:term-level 查询也会返回分数,但Y有些分数是没有什么意义的。最好用explain查看一下打分的原因,比如term就会打bm25分,还是又用的,而terms就是给个常量1分。
term-level 查询不进行分词分析。
term-level 查询包括:
non-expensive: term, terms, ids, exists
expensive: wildcard, range, prefix,fuzzy, regex,join queries, others
expensive是指比较费性能,耗时会较长的查询。可通过控制集群参数来关闭enpensive查询权限。
PUT _cluster/settings
{
"transient": {
"search.allow_expensive_queries": "false"
}
}
4.1.1 term
# 缩写版
GET movies/_search
{
"query": {
"term": {
"title": "The Godfather" # 不适合搜索text类型字段
}
}
}
# 展开版
GET movies/_search
{
"query": {
"term": {
"title": {
"value": "The Godfather",
"boost": 2 #支持boost参数
}
}
}
}
4.1.2 terms
# Terms query
GET movies/_search
{
"query": {
"terms": {
"certificate": ["PG-13","R"]
}
}
}
terms的数组里最多可写的字段受index.max_terms_count参数控制,默认65,536个。
PUT movies/_settings
{
"index":{
"max_terms_count":10
}
}
terms有一个变种查询,可利用其他文档自身相关信息,作为查询term。
GET movies/_search
{
"query": {
"terms": {
"director": {
"index":"famouse_person", # 指定索引下
"country":"en", # 指定所有country字段位en的文档
"path":"name" # 字段name的值,组成terms在director中查询
}
}
}
}
4.1.3 ids
批量查询_id字段的语句。
GET movies/_search
{
"query": {
"ids": {
"values": [10,4,6,8]
}
}
}
4.1.4 exists
返回字段存在的文档。如果想获取不存在的文档,则需要用bool语句的must_not+exists。
GET movies/_search
{
"query": {
"exists": {
"field": "title"
}
}
}
4.1.5 range
对于 date和数值类型数据,取范围。支持lt,gt,lte,gte
GET movies/_search
{
"query": {
"range": {
"rating": {
"gte": 9.0,
"lte": 9.5
}
}
}
}
对于date类型字段,ES还支持一定的数学计算:
now 表示当前时间
y for years
M for moths
w for weeks
d for days
h for hours
m for minutes
s for seconds
# Range query with date math
GET movies/_search
{
"query": {
"range": {
"release_date": {
"lte": "15-02-1995||+2d" # +表示未来,-表示过去
}
}
}
}
# Range query with date match using now
GET movies/_search
{
"query": {
"range": {
"release_date": {
"lte": "now+1y"
}
}
}
}
4.1.6 wildcard
可理解成term的通配符模式。
*:匹配0或多个任意字符
?:匹配1个任意字符
GET movies/_search
{
"query": {
"wildcard": {
"title": {
"value": "god*"
}
}
}
}
4.1.7 prefix
前缀匹配查询
GET movies/_search
{
"query": {
"prefix": {
"genre.original": {
"value": "Ad"
}
}
}
}
ES会根据前缀去派生查询,所以这个速度是比较慢的。可以再创建索引时,指定index_prefixes参数来预先生成前缀,加速匹配。
PUT boxoffice_hit_movies_custom_prefix_sizes
{
"mappings": {
"properties": {
"title":{
"type": "text",
"index_prefixes":{
"min_chars":4, #默认2
"max_chars":10 #默认5
}
}
}
}
}
4.1.8 fuzzy
用于拼写错误的查询。fuzziness参数表示编辑距离。增、删、改都算1个编辑距离。fuzziness设置的话默认是AUTO:
查询字段长度 | fuzziness (编辑距离) | 说明 |
---|---|---|
0-2 | 0 | 若长度小于等于2,则编辑距离为0,fuzzy相当于不启用 |
3-5 | 1 | |
>5 | 2 |
GET movies/_search
{
"query": {
"fuzzy": {
"genre": {
"value": "drma",
"fuzziness": 1
}
}
}
}
4.2 full-text 查询
match_all,match,match_phrase
4.2.1 match_all
相关分1.0。返回索引所有文档
GET books/_search
{
"query": {
"match_all": {}
}
}
4.2.2 match
语法:
# 简化版
GET books/_search
{
"query": {
"match": { #A
"FIELD": "SEARCH TEXT" #B
}
}
}
# 展开版
GET books/_search
{
"query": {
"match": {
"FIELD": { #A
"query":"<SEARCH TEXT>", #B
"<parameter>":"<MY_PARAM>", #C
}
}
}
}
SEARCH TEXT会先经过分词。分词后的term,和FIELD匹配默认是 “OR”关系,匹配得越多,相关分数越高。
parameter支持:官方文档看全部参数
operator:AND 或 OR,分词后的term匹配需满足的关系。AND表示必须都匹配。
minimum_should_match:至少匹配几个term,operator为OR时才有效。支持带符号数值(如3
,-2
)和带符号百分比(20%
,-20%
),以及它们的组合(2<80%
,2<-20%
)。百分比时需匹配的term个数为总数*百分比
向下取整。2<80%
含义为当term总数<=2
个时,需全部匹配;当>2
个时,需至少匹配总数*百分比
向下取整个。
fuzziness:和fuzzy中的参数使用方式一样。
analyzer:指定搜索时的分析器。
lenient:忽略数据类型转换异常
auto_generate_synonyms_phrase_query:是否开启同义词增强功能,默认为true。
GET books/_search
{
"query": {
"match": {
"title": {
"query": "Java Complete Guide",
"operator": "AND" # 默认是OR
"analyzer": "whitespace"
}
}
}
}
4.2.3 match_phrase
按分词匹配的时候,要保持和query中一样的顺序,且各term间的间距不能超过参数slop(默认为0),即查出来的内容中的term默认必须都是连续的。
GET books/_search
{
"query": {
"match_phrase": {
"synopsis": "book for every Java programmer"
}
}
}
GET books/_search
{
"query": {
"match_phrase": {
"synopsis": {
"query": "for every Java programmer book",
"slop": 1 #可间隔1个词
}
}
}
}
4.2.4 match_phrase_prefix
和match_phrase类似,只不过把最后一个词当做前缀匹配。最后一个term的模糊匹配数控制:max_expansions 默认值为50(可自己设定)。注意:"max_expansions"的值最小为1,哪怕设置为0,依然会 + 1个通配符匹配;所以,尽量不要用该语句,因为,最后一个term始终要去扫描大量的索引,性能可能会很差。
GET books/_search
{
"query": {
"match_phrase_prefix": {
"tags": {
"query": "concepts found",
"slop":1
"max_expansions": 2
}
}
}
}
4.2.5 match_bool_prefix
类似match_phrase_prefix,差别是分词后的term在匹配时可以不按顺序。官方。
4.2.6 multi_match
多个Fields之间的查询关系是 or。
字段^数字:表示增强该字段评分倍数(权重影响相关性评分)。
参数type指定了multi_match相关性分_score的取值方法,支持:
- best_fields(默认): 从匹配的任意 field 查找文档, 但是用 field相关分最高的一个作为 _score,支持tie_breaker参数,等价写法为dis_max。operator:AND影响的是每个term在field中的表现,filed之间的关系还是or。
- most_fields:从匹配的任意 field 查找文档, 相加所有field的相关分作为_score,等价写法为should。
- cross_fields: cross_fields 使用词中心式(term-centric)的查询方式,这与 best_fields 和 most_fields 使用字段中心式(field-centric)的查询方式非常不同,它将所有字段当成一个大字段,并在 大字段 中查找 每个词,这样相关性分上会和most_fields 有差异 。operator控制的是field之间的关系。不同field会根据使用的分析器,分成不同的组,operator控制的就是组之间的关系。
- phrase:每个field跑一个match_phrase查询, 用 field相关分最高的一个作为 _score。
- phrase_prefix:每个field跑一个match_phrase_prefix查询, 用 field相关分最高的一个作为 _score。
- bool_prefix:每个field跑一个match_bool_prefix查询, 相加所有field的相关分作为_score。
GET books/_search
{
"_source": false,
"query": {
"multi_match": {
"query": "Java",
"fields": [
"title^2",
"synopsis",
"tags"
]
}
}
}
4.2.7 dis_max
实际属于复合查询。best_fields的type下,ES实际上是吧multi_match语句在后台会改写成dis_max语句来运行。dis_max的_score为:
_
s
c
o
r
e
=
max
(
S
q
)
+
t
i
e
_
b
r
e
a
k
e
r
⋅
(
sum
(
S
q
)
−
max
(
S
q
)
)
\_score=\max{(S_q)}+tie\_breaker\cdot(\text{sum}( S_q)-\max{(S_q)})
_score=max(Sq)+tie_breaker⋅(sum(Sq)−max(Sq))
S
q
S_q
Sq为所有子query的得分集合,tie_breaker
默认值为0。
# Best fields - with a tie breaker
GET books/_search
{
"_source": false,
"query": {
"multi_match": {
"query": "Design Patterns",
"type": "best_fields",
"fields": ["title","synopsis"],
"tie_breaker": 0.5
}
}
}
# 6.9938974 + 0.5 *(2.9220228 2.7801032 2.6008778)
#等价的 dis_max query
GET books/_search
{
"_source": false,
"query": {
"dis_max": {
"queries": [
{"match": {"title": "Design Patterns"}},
{"match": {"synopsis": "Design Patterns"}}],
"tie_breaker": 0.5
}
}
}
4.2.8 query_string
query_string是吧URI的编写方式放到DSL中的一种方法,同时也支持原生DSL相关的写法,主要是支持逻辑操作的查询比较方便。
原生DSL写法时,query中的字符串会先分词,再搜索。
default_operator:分词后term间的关系由default_operator控制,默认为OR。
default_field:只搜索一个field的时候指定。
fields:搜索多个field的时候指定,field之间的关系是OR。
GET books/_search
{
"query": {
"query_string": {
"query": "author:Bert AND edition:2 and release_date>=2000-01-01" # 模拟URI的能力
}
}
}
GET books/_search
{
"query": {
"query_string": {
"query": "Patterns" #不限定field的时候,以term方式在所有field中搜索
}
}
}
GET books/_search
{
"query": {
"query_string": {
"query": "Patterns",
"fields": ["title","synopsis","tags"] #限定搜索field
}
}
}
GET books/_search
{
"query": {
"query_string": {
"query": "Design Patterns",
"default_field": "title",
"default_operator": "AND"
}
}
}
GET books/_search
{
"query": {
"query_string": {
"query": "\"making code better\"", #类似match_phrase的功能
"default_field": "synopsis",
"phrase_slop": 1
}
}
}
GET books/_search
{
"query": {
"query_string": {
"query": "Pattenrs~", # ~打开fuzzy功能,"Pattenrs~10"表示编辑距离为10
"default_field": "title"
}
}
}
query_string中的fuzzy编辑距离默认为2,且采用的是 Damerau-Levenshtein 距离(可以移位)。如果要修改默认距离,则用~10
修改为10。
simple_query_string
simple_query_string支持操作符。
Operator | Description |
---|---|
| | OR |
+ | AND |
- | NOT |
~ | Fuzzy query |
* | Prefix query |
“ | Phrase query |
GET books/_search
{
"query": {
"simple_query_string": {
"query": "Java + Cay",# 在title中搜Java且Cay
"default_field": "title"
}
}
}
4.3 compound 查询
compound 查询有以下几种:
• Boolean query: bool
• Constant score query: constant_score
• Function score: function_score
• Boosting query: boosting
• Disjunction max query: dis_max
4.3.1 bool
bool查询支持四种语句(clauses): must, must_not, should,和 filter。四种语句的子query中支持自定义查询名称:
_name:给query命名,便于问题定位和减少重复query。
GET books/_search
{
"query": {
"bool": { #A A bool query is a combination of conditional boolean clauses
"must": [{ ...,"_name":"must条件1"},{ ...,"_name":"must条件2"}],#B The criteria must match with the documents
"must_not": [{ }],#C The criteria must-not match (no score contribution)
"should": [{ }],#D The query should match
"filter": [{ }]#E The query must match (no score contribution)
}
}
}
短语 | 说明 |
---|---|
must | 子句(查询)必须出现在匹配的文档中,并将有助于相关性得分。 |
must_not | 子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。 |
should | 子句(查询)应出现在匹配的文档中(可以不出现),并将有助于相关性得分。【注意should的最小匹配数】 |
filter | 必须匹配,类似must语句,子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。 |
注意:
- 4种语句的子句,支持 Full text queries 和 Term-level queries , bool ,constant_score ;
- 只有must 和 should 子句会计算相关性评分;filter 和 must_not 子句都是在过滤器context中执行,计分被忽略,并且子句被考虑用于缓存。
示例:
GET books/_search
{
"query": {
"bool": {
"must": [{"match": {"author": "Joshua"}}],
"must_not":[{"range":{"amazon_rating":{"lt":4.7}}}],
"should": [{"match": {"tags": "Software"}}],
"filter":[
{"range":{"release_date":{"gte": "2015-01-01"}}},
{"term": {"edition": 3}}
]}
}
}
should子句中的参数minimum_should_match和前面match语句中的使用方法一样,在bool中,默认值为两种情况:
- must存在时,默认为1
- must不存在时,默认为0
4.3.2 constant_score
一共两个参数filter,boost。官方。
说明仅支持filter子句。
正常情况filter的score为0,boost可指定filter的返回分。
GET /_search
{
"query": {
"constant_score": {
"filter": {
"term": { "user.id": "kimchy" }
},
"boost": 1.2
}
}
}
4.3.3 boosting
支持三个必选参数:
positive:接子query,子query可以使 term-level,full-text level和bool等
negative:接子query,子query可以使 term-level,full-text level和bool等
negative_boost:0-1的一个值
1)根据 positive 下的查询语句检索,得到结果集;
2)在上述的结果集中,对于那些同时还匹配 negative 查询的文档,将通过文档的原始 _score 与 negative_boost 相乘的方式重新计算相关性得分:
_
s
c
o
r
e
=
negative_boost
∗
positive评分
\_score=\text{negative\_boost}*\text{positive评分}
_score=negative_boost∗positive评分
GET /_search
{
"query": {
"boosting": {
"positive": {
"term": {
"text": "apple"
}
},
"negative": {
"term": {
"text": "pie tart fruit crumble tree"
}
},
"negative_boost": 0.5
}
}
}
4.3.4 rescore
rescore 和 上面的 boosting 是比较相似的,都是在 query 结果集的基础上重新修改相关性得分。但是修改的算法是不一样的,根据场景需求,选择即可。
同时 rescore 可以利用 window_size 参数控制重新计算得分的文档数量,在数据量较大的情况,适当控制 window_size 参数,性能上会比 Boosting Query好
4.3.5 dis_max
见4.2.7章节,或官方文档。queris中的子查询必须满足至少一个。
GET /_search
{
"query": {
"dis_max": {
"queries": [
{ "term": { "title": "Quick pets" } },
{ "term": { "body": "Quick pets" } }
],
"tie_breaker": 0.7
}
}
}
4.3.6 function_score
提供了用户自定义的对相关分进行修正的能力。官方文档。
# 展开版
GET books/_search
{
"query": {
"function_score": {
"query": { #A
#类似原最外层的query
},
"<parameter>":"<MY_PARAM>", #C
}
}
}
parameter中重要参数:
- functions:用于加权的function数组,只有一个function时,可以不用functions,直接写相关函数替代即可。functions里的重要参数:
-
filter:过滤器得到的所有文档的_score都是1,如果不用filter,那么默认使用的是match_all查询。通常和weight一起使用。
-
weight:设置一个简单而不被规范化的权重提升值(boost会被规范化),即
news_score=weight*old_score
,weight的默认值是1.0,当设置了weight,这个weight就会和评分函数的值相乘,在通过score_mode和其他funcitions分数合并。还有一个注意的点,当score_mode 为avg的时候,两个functions的func_score分别为 1 和 2 且他们的weight为3和4,那么他们的最终分为(1*3+2*4)/(3+4)
而不是(1*3+2*4)/2
。 -
random_score:返回均匀分布的
[0,1)
的值。支持两个参数seed
和field
。score=random(seed, field的最小值(如果是个多值field), 盐值(由索引名称和shard Id决定))。如果seed、field、盐值这三个值不变,那对于同一个文档,每次得到的score都相同。- seed:可以不填,默认值是一个带符号的随机值(每次请求都会变化,即效果等价于填入request_id)
- field:可以不填(seed不填,只天field也无效),默认会加载fileddata里的
_id
,会消耗内存,耗费性能。最好指定一个对于文档来说是全局唯一的值。推荐_sed_no
,该值每个文档唯一,但如果文档有更新,该值会改变。
-
field_value_factor:根据某个filed的值返回。注意:field_value_score 不能返回负数值,否则会报错,建议用filter做过滤。
- field:指定用于加权的字段(
func_score=doc['field_name'].value
) - factor:field_value的调权值,默认为1。
func_score=factor*doc['field_name'].value
- modifier:func_score的调权函数:
new_score=modifier(func_score)=modifier(factor*doc['field_name'].value)
。支持none, log(会产生负值,建议用log1p), log1p, log2p, ln(会产生负值,建议用ln1p), ln1p, ln2p, square, sqrt(field为负值会报错), or reciprocal(field为负值和0会报错). 默认为none。 - missing:filed不存在时的缺省值ben。
- field:指定用于加权的字段(
-
script_score:写脚本,脚本中可引用各种ES衰减函数和各种选择的编程语言支持的函数。
- script:脚本详情
- source 或 id:source为脚本源码,id为一个保存的脚本名(通过 stored script APIs创建和管理保存脚本)。
- params:script中用到的参数
- lang:脚本编程语言,默认painless
- script:脚本详情
-
衰减函数:
- DECAY_FUNCTION:可选衰减函数gauss, linear, exp
- multi_value_mode:如果field是一个多值字段,则最终用于参与衰减计算的distance 有多种选择:min(默认,将选择最接近原点的值来确定distance)、max、avg、sum。
- FIELD_NAME:当作衰减函数的自变量,只能是numeric, date, 或 geopoint 类型
- origin : 中心点,用于计算distance 。distance参与后续的计算。支持数值、时间 以及 “经纬度地理座标点”(最常用) 的字段。
- offset : 默认值0,从 origin 为中心,为他设置一个偏移量offset覆盖一个范围,在此范围内所有的评分_score也都是和origin一样满分1.0。
- scale : 衰减率,即是一个文档从origin下落时,_score改变的速度。
- decay : 在 scale 处所得的评分_score,默认为0.5 (一般不需要改变,这个参数使用默认的就好了)
- DECAY_FUNCTION:可选衰减函数gauss, linear, exp
-
# field_value_factor
{
"query": {
"function_score": {
"query": {... },
"field_value_factor": {
"field": "field_name" #如: "field": "rating_score"
"factor": 1.2,
"modifier": "sqrt",
"missing": 1
}
}
}
}
# script_score
{
"query": {
"function_score": {
"query": {... },
"script_score": {
"script": {
"source": "Math.log(a + doc['my-int'].value)", #甚至可以定义多值,并经过很复杂的逻辑计算,最终return value。
"params": {"a": 2}
}
}
}
}
}
# 衰减函数
{
"query": {
"function_score": {
"query": {... },
"DECAY_FUNCTION": {
"FIELD_NAME": {
"origin": "11, 12",# "2013-09-17"
"scale": "2km", # "10d"
"offset": "0km", # "5d"
"decay": 0.33
}
}
}
- score_mode: functions中各函数得分的加权方式
选项 | 说明 |
---|---|
multiply | scores are multiplied (default) |
sum | scores are summed |
avg | scores are averaged |
first | the first function that has a matching filter is applied |
max | maximum score is used |
min | minimum score is used |
- boost_mode: functions最后得分和query相关分的加权方式:
选项 | 说明 | 说明 |
---|---|---|
multiply | query score and function score is multiplied (default) | new_score = query_score * func_score |
replace | only function score is used, the query score is ignored | new_score = func_score,直接替换query_score |
sum | query score and function score are added | new_score = query_score + func_score |
avg | average | new_score = avg(query_score ,func_score) |
max | max of query score and function score | new_score= max(query_score, func_score) |
min | min of query score and function score | new_score= min(query_score, func_score) |
- max_boost:限制functions函数的最大效果,就是限制
func_score
最大能多少,但是不会限制query_score
。如果func_score
超过了max_boost的限制值,会把func_score
的值设置成max_boost。默认值为FLT_MAX。 - min_score:过滤functions加权后 _score(即new_score)小于min_score的文档。注意:运行机制是先完成打分,再过滤。
4.4 特殊查询
官方提供了多种特殊查询方式:如
distance_feature query
more_like_this query
percolate query
rank_feature query
script query(线性扫描,很慢)
script_score query
wrapper query
pinned query
有时间可把官方DSL一栏的都梳理一遍。
调整相关度
参考教程
boost
注意:1)boost 可用于任何查询语句;2)这种提升或降低并不一定是线性的,新的评分 _score 会在应用权重提升之后被归一化 ,每种类型的查询都有自己的归一算法
高亮
highlight和query同一层级。
GET books/_search
{
"query": {
"match_phrase": {
"title": "must-have book for every Java programmer"
}
},
"highlight": {#A The highlight object at the same level as query object
"fields": {# B mention which fields we wish to have highlights
"title": {}
}
}
}
同义词处理
https://www.elastic.co/guide/en/elasticsearch/reference/8.5/analysis-synonym-graph-tokenfilter.html
常用接口
_analyze接口
分析器接口。也可以在路径中添加索引名称以使用对应索引的分析器。
# 优先使用POST, GET在Kibana上也可以但在es head会报错
POST /es_test/_analyze
{
"text":["apple egg book"]
# "analyzer": "standard"
}
# 拆得更细用
GET _analyze
{
"tokenizer" : "standard",
"filter" : ["lowercase"],
"text" : "THE Quick FoX JUMPs"
}
_count 接口
Elasticsearch提供了查看文档总数的_count接口,可通过GET或POST方法请求该接口。在请求该接口的路径上,可以添加索引、映射类型,以限定统计文档数量的范围。所以在示例中对_count接口的请求都是正确的:
GET _count
GET index/_count
POST kibana_sample_data_logs/_count
{
"query": {
"match": {
"message": "chrome"
}
}
}
_bulk 接口
bulk对JSON串的有着严格的要求。每个JSON串不能换行,只能放在同一行
,同时,相邻的JSON串之间必须要有换行(Linux下是\n;Window下是\r\n)。bulk的每个操作必须要一对JSON串(delete语法除外)。
{ action: { metadata }}
{ request body }
{ action: { metadata }}
{ request body }
bulk的操作类型:
- create 如果文档不存在就创建,但如果文档存在就返回错误
- index 如果文档不存在就创建,如果文档存在就更新
- update 更新一个文档,如果文档不存在就返回错误
- delete 删除一个文档,如果要删除的文档id不存在,就返回错误
其实可以看得出来index是比较常用的。还有bulk的操作,某一个操作失败,是不会影响其他文档的操作的,它会在返回结果中告诉你失败的详细的原因。
POST _bulk
{ "index" : {"_index": "students","_id":"10"}}
{ "name" : "smith" }
{ "delete" : {"_index": "test","_id":"5"}}
{ "create": {"_index": "test","_id":"11"}}
{ "age" : 30,"name":"Candy" }
{ "update" : {"_id" :"1","_index" : "students"} }
{ "doc": {"age" : "20"}}
# 或者把index写到请求中
POST /es_test/_doc/_bulk
{"create":{"_id": "1"}}
{"id": "1","title":"my love fruit","content":"t1 t2 t3","tags":["t1","t2","t3"]}
{"create":{"_id": "2"}}
{"id": "2","title":"my early love fruit","content":"t3 t2 t4","tags":["t3","t2","t4"]}
{"create":{"_id": "3"}}
{"id": "3","title":"my future love fruit","content":"t2 t5 t6 t3","tags":["t2","t5","t6","t3"]}
POST /es_test/_doc/_bulk
{"delete":{"_id": "1"}}
{"delete":{"_id": "2"}}
{"delete":{"_id": "3"}}
_mapping 接口
GET获取索引的mapping信息,或者PUT 创建或修改mapping信息。
# 获取
GET index/_mapping
PUT index/_mapping
{..}
_explain 接口
获取评分或者错误的详细解释。
GET /_search?explain
{
"query" : { "match" : { "tweet" : "honeymoon" }}
}
# 等价 explain 为true
GET /_search
{
"query" : { "match" : { "tweet" : "honeymoon" }},
"explain":true
}
# 格式: /index/type/id/_explain ,可用于解释,为什么一个id没有被match。7.x以下
GET/POST /es_test/_doc/2/_explain
{
"query": {
"term": {"content": "t0" }
}
}
# 可看到filter过滤原因:"description": "content:t0 doesn't match id 1"
GET /es_test/_doc/2/_explain
{
"query": {
"bool" : {
"filter" : { "term" : { "content" : "t0" }},
"should" : [{ "match" : { "title" :"my" }}]
}
}
}
# 7.x及以上,格式: /index/_explain/id,因为只有_dco类型,所以不需要指定类型了。
GET /es_test/_explain/2/
{...}
# 如果碰到禁用以上_explain方式的系统,一般可以通过转换成bool查询实现,但这种只能查看能匹配的文章。
{ "query": {
"bool" : {
"filter" : { "term" : { "_id" : "xxx" }},
"must" : [{原query}]
}
},
"explain":"true"
}
_search接口
查询接口,很常用,若不配合query,则返回index下所有文档的meta+_source信息,等价于match_all
GET books/_search
# 等价
GET books/_search
{
"query": {
"match_all": { }
}
}
这里讲讲如何获取想要的字段信息。包括_source字段和sotored字段。
# 获_source取字段信息,7.0以上用_source_includes,多个s
GET /es_test/_doc/2?_source_include=title,content
# 也可以用:
POST es_test/_search
{
"query": {
"term": {
"_id": "2"
}
},
"fields": ["title", "content"],
"_source": false #若不用fields可直接开成true
}
# 或
POST es_test/_search
{
"query": {
"term": {
"_id": "2"
}
},
"_source": {
"includes": ["title", "content"]
}# 或者简写成 "_source": ["title", "content"]
}
# 获取stored字段信息
GET twitter/_doc/1?stored_fields=title,content
# 或
POST es_test/_search
{
"query": {
"term": {
"_id": "2"
}
},
"stored_fields": ["title", "content"]
}
_refresh 接口
_refresh接口用于主动刷新一个或多个索引,将已经添加的文档编入索引以使它们在检索时可见。在调用该接口时,可以直接调用或与一个或多个索引起使用, 还可以使用_all刷新所有索引。
GET 索引1/_refresh
POST _refresh
GET _all/_refresh
POST 索引1,索引2/_refresh
_stats 接口
_stats接口用于查看索引上不同操作的统计数据,可以直接请求也可以与索引名称一起使用。_stats接口返回的统计数据非常多,如果只对其中某一组统计数据感兴趣,可以在_stats接口后附加统计名称。 例如以下对_stats接口的调用都是正确的:
GET _stats
GET _stats/store
GET kibana_sample_data_flights/_stats
GET kibana_sample_data_flights/_stats/fielddata
_validate接口
_validate接口用于在不执行查询的情况下,评估一个查询是否合法可执行,这通常用于验证执行开销比较高的查询。_validate接口可通过GET或POST方法请求,请求路径中必须要包含_validate/query,也可以在路径中添加索引名称以限定查询执行的范围。类似_search接口。示例:
POST _validate/query
{
"query": {
...
}
}
# 解释具体错误
GET /es_test/_validate/query?explain
{
"query": {
...
}
}
_mget 接口
一条一条的查询,比如说要查询100条数据,那么就要发送100次网络请求,这个开销还是很大的,如果批量查询的话,查询100条数据,就只要发送1次网络请求,网络请求的性能开销缩减100倍。
GET /_mget
{
"docs": [
{
"_index": "es_test",
"_id": "1"
},
{
"_index": "es_test",
"_id": "2"
}
]
}
_field_caps接口
_field_caps接口用于查看某一字段支持的功能,主要包括字段是否可检索以及是否可聚集等。需要查看的字段可以通过 URI参数fields设置,可以使用GET或POST方法请求。在请求地址中,还可以添加索引名称以限定查询范围。
GET _field_caps?fields=title
POST es_test/_field_caps?fields=title,content
容量控制接口
_split接口:对新索引做分片上的操作
_shrink接口:对新索引做分片上的操作
_reindex接口:将文档复制到新索引
性能调优
分片、线程池
参考:
《Madhusudhan Konda - Elasticsearch in Action Second Edition Version 11 (2022, Manning Publications)》
GIt: https://github.com/madhusudhankonda/elasticsearch-in-action/wiki
GIT2:https://github.com/madhusudhankonda/elasticsearch-in-action/tree/main/kibana_scripts
http://mp.weixin.qq.com/mp/homepage?__biz=MzIxMjE3NjYwOQ==&hid=5&sn=b9c85139ca524fc7823379f4a2da99ba&scene=18#wechat_redirect文章来源:https://www.toymoban.com/news/detail-468814.html
https://opster.com/elasticsearch-guides/文章来源地址https://www.toymoban.com/news/detail-468814.html
到了这里,关于ES教程:从入门到入土的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!