ES教程:从入门到入土

文章目录

一、环境准备

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
  • 文档排序类
    • 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自动生成字段和类型的方式,两种情况:

  1. 未定义mapping,就创建索引
  2. 定义了mapping,未包含新字段,增加新字段。

ES自动推断类型的规则:

3.1.2 显示mapping(Explicit Mapping)

ES提供两种用于maping的操作:

  1. PUT index 创建阶段,提供全量字段信息。
  2. 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 配置。
场景分析器

analyzerlogical namedescription
standard analyzerstandardstandard tokenizer, standard filter, lower case filter, stop filter
simple analyzersimplelower case tokenizer
stop analyzerstoplower case tokenizer, stop filter
keyword analyzerkeyword不分词,内容整体作为一个token(not_analyzed)
pattern analyzerwhitespace正则表达式分词,默认匹配\W+
language analyzerslang各种语言
snowball analyzersnowballstandard tokenizer, standard filter, lower case filter, stop filter, snowball filter
custom analyzercustom一个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)

查询方式有两种:

  1. 基于URI请求的查询,如:GET movies/_search?q=title:Godfather可获取索引movies中title匹配Godfather 的文档。
  2. 基于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将所有查询自动分为两类:

  1. query context:会计算相关分,返回结果会返回这个分数。
  2. 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*会匹配到titletitle.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-20若长度小于等于2,则编辑距离为0,fuzzy相当于不启用
3-51
>52
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支持操作符。

OperatorDescription
|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中,默认值为两种情况:

  1. must存在时,默认为1
  2. 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_boostpositive评分

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)的值。支持两个参数seedfield。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。
    • script_score:写脚本,脚本中可引用各种ES衰减函数和各种选择的编程语言支持的函数。

      • script:脚本详情
        • source 或 id:source为脚本源码,id为一个保存的脚本名(通过 stored script APIs创建和管理保存脚本)。
        • params:script中用到的参数
        • lang:脚本编程语言,默认painless
    • 衰减函数:

      • 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 (一般不需要改变,这个参数使用默认的就好了)
# 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中各函数得分的加权方式
选项说明
multiplyscores are multiplied (default)
sumscores are summed
avgscores are averaged
firstthe first function that has a matching filter is applied
maxmaximum score is used
minminimum score is used
  • boost_mode: functions最后得分和query相关分的加权方式:
选项说明说明
multiplyquery score and function score is multiplied (default)new_score = query_score * func_score
replaceonly function score is used, the query score is ignorednew_score = func_score,直接替换query_score
sumquery score and function score are addednew_score = query_score + func_score
avgaveragenew_score = avg(query_score ,func_score)
maxmax of query score and function scorenew_score= max(query_score, func_score)
minmin of query score and function scorenew_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://opster.com/elasticsearch-guides/

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值