Elasticsearch搜索引擎(搜索)

一个优秀的elasticsearch工程师对elastic官网内容和案例模板要非常清楚,因为elasticsearch的api本就复杂规律性不像sql那么简单易用。

Search API

[https://www.elastic.co/guide/en/elasticsearch/reference/8.1/search-search.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.1/se arch-search.html)

实现对 es 中存储的数据进行查询分析,endpoint 为 _search,如 下

  • GET /_search _
  • _GET /my_index/_search
  • GET /my_index1,my_index2/_search _
  • GET /my*/_search

查询主要有两种形式

  • URI Search
  • Request Body Search

操作简便,方便通过命令行测试

  • 仅包含部分查询语法
  • GET /my_index/_search?q=user:alfred

通过 url query 参数来实现搜索,常用参数如下:

  • q 指定查询的语句,语法为 Query String Syntax
  • q 中不指定字段时默认查询的字段,如果不指定,es 会查 询所有字段
  • sort 排序 ◆timeout 指定超时时间,默认不超时
  • from,size 用于分页

eg.查询 user 字段包含 alfred 的文档,结果按照 age 升序 排列,返回第5~14个文档,如果超过 1s 没有结束,则 以超时结束

GET /my_index/_search?q=alfred&df=user&sort=age:asc&from=4&size=10 &timeout=1s

提供完备查询语法 Query DSL(Domain Specific Language)

  • 将查询语句通过 http request body 发送到 es,主要包含如下参 数
    • query 符合 Query DSL 语法的查询语句
    • from, size
    • timeout
    • sort

eg.字段查询用户叫alfred的人

1
2
3
4
5
6
7
8
GET /my_index/_search
{
"query": {
"term": {
"user": "alfred"
}
}
}

基于 JSON定义的查询语言,主要包含如下两种类型:

  • 字段类查询
    • 如 term, match, range 等,只针对某一个字段进行查询
  • 复合查询
    • 如 bool 查询等,包含一个或多个字段类查询或者复合查 询语句

Match Query

对指定字段进行全文检索(会分词),最常用的查询语法,API 示例如下:

1
2
3
4
5
6
7
8
9
GET test_search_index/_search
{
"query": {
"match": {
//字段名:查询值
"username": "alfred way"
}
}
}

or和and

  • 通过 operator 参数可以控制单词间的匹配关系,可选项为 or 和 and
1
2
3
4
5
6
7
8
9
10
11
GET test_search_index/_search
{
"query": {
"match": {
"username": {
"query": "alfred way",
"operator": "and"
}
}
}
}

minimum_should_match

  • 通过 minimum_should_match 参数可以控制需要匹配的单词数
1
2
3
4
5
6
7
8
9
10
11
GET test_search_index/_search
{
"query": {
"match": {
"username": {
"query": "alfred way",
"minimum_should_match": "2"
}
}
}
}

Term Query

将查询语句作为整个单词进行查询,即不对查询语句做分词处理, 如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GET test_search_index/_search
{
"query": {
"term": {
"username": "alfred"
}
}
}
//一次传入多个单词进行查询,如下所示:
GET test_search_index/_search
{
"query": {
"terms": {
"username": [
"alfred",
"way"
]
}
}
}

Match Phrase Query

对指定字段进行检索,对于查询词语有顺序要求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GET test_search_index/_search
{
"query": {
"match_phrase": {
"job": "java engineer"
}
}
}
//通过 slop 参数可以控制单词间的间隔
GET test_search_index/_search
{
"query": {
"match_phrase": {
"job": {
"query": "java engineer",
"slop": "1"
}
}
}
}

Range Query

范围查询主要针对数值和日期类型,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
GET test_search_index/_search
{
"query": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
//日期
GET test_search_index/_search
{
"query": {
"range": {
"birth": {
"gte": "1990-01-01"
}
}
}
}
GET test_search_index/_search
{
"query": {
"range": {
"birth": {
"gte": "now-20y"
}
}
}
}
  • 日期单位主要有如下几种:
    • y - years
    • M - months
    • w - weeks
    • d - days
    • h - hours
    • m - minutes
    • s - seconds

Boolean Query

布尔查询由一个或多个布尔子句组成

  • filter:只过滤,不计算得分
  • must:文档必须符合 must 中的所有条件,会影响相关性得分
  • must_not:must相反
  • should:文档可以符合 should 中的条件,会影响相关性得分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{}
],
"must_not": [
{}
],
"should": [
{}
],
"filter": [
{}
]
}
}
}

Filter

Filter 只搜索匹配查询的文档,不会进行相关性算分

  • filter 查询结果会有缓存,降低查询延迟
  • 做简单匹配查询且不考虑算分时,推荐使用 filter 替代 query 等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET test_search_index/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"username": "alfred"
}
}
]
}
}
}

Must

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//查询 username 包含 alfred并且 job 包含 specialist 关键词的文档列表
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"username": "alfred"
}
},
{
"match": {
"job": "specialist"
}
}
]
}
}
}

Must not

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"job": "java"
}
}
],
"must_not": [
{
"match": {
"job": "ruby"
}
}
]
}
}
}

Should

Should 使用分两种情况:

  • bool 查询中只包含 should ,不包含 must 查询

    • 只包含 should 时,文档必须满足至少一个条件

    • minimum_should_match 可以控制满足条件的个数或者百分比

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      GET test_search_index/_search
      {
      "query": {
      "bool": {
      "should": [
      {
      "term": {
      "job": "java"
      }
      },
      {
      "term": {
      "job": "ruby"
      }
      },
      {
      "term": {
      "job": "specialist"
      }
      }
      ],
      "minimum_should_match": 2
      }
      }
      }
  • bool 查询中同时包含 should 和 must 查询

    • 同时包含 should 和 must 时,文档不必满足 should 中的条件, 但是如果满足条件,会增加相关性得分

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      //查询 username 包含alfred 的文档,同时将 job 包含 ruby 的文档排在前面
      GET test_search_index/_search
      {
      "query": {
      "bool": {
      "must": [
      {
      "term": {
      "username": "alfred"
      }
      }
      ],
      "should": [
      {
      "term": {
      "job": "ruby"
      }
      }
      ]
      }
      }
      }

Count API

获取符合条件的文档数, endpoint 为 _count

1
2
3
4
5
6
7
8
GET test_search_index/_count
{
"query": {
"match": {
"username": "alfred"
}
}
}

Sort

es 默认会采用相关性算分排序,用户可以通过设定 sorting 参数 来自行设定排序规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//按出生日期排序
GET test_search_index/_search
{
"sort": {
"birth": "desc"
}
}
// 按照多个字段排序分别按照出生日期倒排,得分倒排,文档内部Id 倒排
GET test_search_index/_search
{
"sort": [
{
"birth": "desc"
},
{
"_score": "desc"
},
{
"_doc": "desc"
}
]
}

注意:字符串排序应避免字符串的索引类型是Text

分页

  • from 指明开始位置
  • size 指明获取总数
1
2
3
4
5
GET test_search_index/_search
{
"from":1,
"size":2
}

搜索高亮

https://www.elastic.co/guide/en/elasticsearch/reference/8.1/highlighting.html

Highlighting,高亮显示匹配词组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
GET /my
-index/_search
{
"query": {
"match_phrase": {
"title": "something"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}

//可以用指定标签高亮
GET /my
-index/_search
{
"query": {
"match_phrase": {
"title": "something"
}
},
"highlight": {
"fields": {
"title": {}
}

"pre_tags": ["<strong>"],
"post_tags": ["</strong>"]
}
}

搜索模板

https://www.elastic.co/guide/en/elasticsearch/reference/8.1/search-template.html

通过参数化,实现查询语句的重用

  • 解放客户端开发人员,只需要传入模板 id 和参数即可实现业务需 求,具体查询语句的编写交由经验丰富的 es 专家实现,并可随时 变更,不需要重新发布客户端
  • 实现查询语句的集中管理,一定程度上实现查询的审计功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//定义
PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
}
}
}
//使用
GET my-index/_search/template
{
"id": "my-search-template",
//参数刚好是之前定义的{{}}中的内容
"params": {
"query_string": "hello world",
"from": 0,
"size": 10
}
}

异步搜索

  • 用于解决请求耗时长,最终超时失败的查询
  • 常见于 Kibana 图表中涉及超大数据量或者复杂查询语句的场景
  • 发送请求后,立刻返回一个 id,后续基于该 id 获取查询结果

https://www.elastic.co/guide/en/elasticsearch/reference/8.1/async-search.html

eg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /logs*/_async_search
{
"query": {
...
},
"sort": [
{
"date": {
"@timestamp": "asc"
}
}
]
}

  • 执行以下API获取结果
    • GET /_async_search/xxxxxx:获取结果
    • GET /_async_search/status/xxxxxx:获取执行状况
    • DELETE /_async_search/xxxxxx:删除异步任务

Elasticsearch搜索引擎(搜索)
https://andrewjiao.github.io/2023/01/12/elasticsearch/ElasticSearch数据查询/
作者
Andrew_Jiao
发布于
2023年1月12日
许可协议