【ELK 笔记】ES search API 使用简记

ElasticSearch 常用的查询语法简记

大白镇楼


ES 中提供了两种查询语法

  • URISearch API: 通过 uri query 参数来实现快速搜索,操作简单,但是不覆盖所有的查询语法
  • Request Body: ES 提供的 DSL 查询语法,覆盖所有的查询,是使用更多的一种。

一. URISearch

URISearch 通过在url 中设置 query 参数实现快速的 CRUD 搜索,常用的参数如下:

  • q: query 的简称,指定查询语句
  • df -> deafult field: 指定的默认查询字段,不指定的话会查询所有字段
  • sort: 指定根据哪个字段排序
  • size 与 from: 用来进行分页
  • timeout: 超时时间

简单实例如下:

新建一条文档

PUT test_index/doc/1
{
  "user": "Alfred",
  "age":14
}

下面语句表示,查询 user 字段中包含 Alfred 的文档,按照 age 进行升序排列,并第 0 个开始查询 10 个,超时时间 1s。我们 from 指定为 0,所以会从查询结果的第一个进行返回是有数据的,如果将 from 指定为 4,则表示返回第 4 到 14 位置的结果,此时结果只有一条在第一的位置,因此此时不会返回数据

GET test_index/_search?q=Alfred&df=user&sort=age:asc&from=0&size=10&timeout=1s
【1】查询模式
  • 泛查询: 不指明字段,在所有字段中匹配
# 查询任意字段中包含 Alfred 的所有文档
GET test_index/_search?q=Alfred
  • 指定字段查询: 查询 user 为 Alfred 的文档
# 查询 user 中包含 Alfred 的所有文档
GET test_index/_search?q=user:Alfred
  • term: 一个个的单词, 匹配任意即可。比如 New York,匹配到 New 或者 York 都可以查询成功
# 查询 user 中含有 New 或者 York 的所有文档
GET test_index/_search?q=user:New York
  • phrase: 词语查询,要用双引号包含,“New York”, 比如精确匹配到 “New York” 才可以
# 查询 user 中含有 "New York" 的所所有文档
GET test_index/_search?q=user:"New York"
【2】布尔操作符与分组查询

URISearch 中使用括号和布尔操作符进行条件分组查询,ES 中的布尔查询操作符如下:

AND (&&), OR(||), NOT(!), +(must), -(must_not)

括号可以用来区分查询的优先级和范围。
示例如下:

# name 中可以包含 New ,必须包含 York
GET /test_index/_search?q=name:(New +York)
# name 中包含 New, 但必须不能包含 York
GET /test_index/_search?q=name:(New -York)
# name 中同时包含 New 和 York
GET /test_index/_search?q=name:(New AND York)
# 括号用于限定,表示name 中包含 New 或者 York 的字段
# 如果不加括号就成了 name 中包含 New 或者其他所有字段中包含 York 的字段的
GET /test_index/_search?q=name:(New OR York)

几点注意:

  • AND OR NOT 必须大写
  • 在 URI Search 中 + 会被解析为空格,需要使用 encode 后的结果: %2B
【2】范围查询

ES 提供了对数字和日志的范围区间查询,其使用规则如下

这里写图片描述

下面是两个简单示例

GET test_search_index/_search?q=username:alfred age:>26
GET test_search_index/_search?q=birth:(>1980 and < 1990)
【3】通配符与正则表达式

URISearch 中还可以通过正则表达式以及通配符进行查询,通配符的匹配规则如下:

这里写图片描述
示例

GET test_search_index/_search?q=username:alf*
GET test_search_index/_search?q=username:/[N]?e.*/

如果熟悉正则表达式的话那么将会非常方便,但是也要注意通配符匹配和正则匹配效率较低,会占用更多的内存,因此不建议使用。 并且没有特殊需求的话千万不要将 * ? 等通配符写在最前面,不然会导致查询所有的文档,极大的影响性能

【4】模糊与近似度查询

ES 中提供了根据字符差异进行搜索的模糊查询,规则如下:

这里写图片描述

简单示例

GET test_index2/_search?q=name:New ~ 1

模糊匹配指的是可以与单词为维度进行模糊查询,比如上面例子中我们查询 roam, 模糊匹配为 1,那么和 roam 差异为 1 的 foam、roams 都可以被查询出来

近似度查询则是以 词语为维度进行模糊匹配。 上面例子中和 fox quick 差异在 5 之内的词语都会被查询出来。

上面就是 URISearch 一些常用的查询方式,下面再来看 Request Body 的查询

二. RequestBody 查询

RequestBody 是 ES 提供的 DSL 查询语句。其基于 JSON 语法定义,通过 http 将 request body 发送到 ES,是最普遍使用的查询方式。其查询方式主要分为 字段查询复合查询

1. 字段类查询

字段类查询包含两类:
* 全文匹配: 对于查询语句先进行分词处理,在与倒排索引进行比较,有 match, match_phrase 等查询类型
* 单词匹配: 不对查询条件进行分词,直接与倒排索引比较,有 term, terms 与 range 等查询类型

2. match query

match 全文检索是 ES 最基本查询方式

GET test_index/_search
{
  "query":{
      "match":{ # 指定查询类型为 match
        # 查询 name 中有 New 或者 York 的文档
        "name": {
          "query": "New York"
        }
      }
  }
}

上面整个查询的基本过程如下:

  • 对查询条件进行分词: New 与 York
  • 得到 name 的倒排索引
  • 分别拿 New 与 York 与倒排索引进行比较,计算相关性算分
  • 汇总相关性算分
  • 根据相关性算分进行排序,返回匹配到的文档

关于相关性算分和 ES 的查询机制后面还会继续学习,这里不作赘述。

常用的查询选项
  • operator

通过查询结果我们可以知道 match 的查询匹配条件相当于 or。即任意一个单词匹配上即可,我们可以通过 operator 指明其为 and 查询,必须匹配所有的单词才可以,示例如下:

GET test_index/_search
{
  "query":{
      "match":{ # 指定查询类型为 match
        # 查询 name 中有 New 和 York 的文档
        "name": {
          "query": "New York"
          "operator": "and"
        }
      }
  }
}
  • minimum_should_match

控制的最小单词匹配数,使用示例如下

GET test_index/_search
{
  "query": {
    "match": {
      "name": {
        "query": "New York",
        # 虽然是 or, 但是我们要求最小匹配数为 2,必须匹配到 New 和 York 才可以成功,达到了 and 的效果。
        "minimum_should_match": 2
      }
    }
  }
}
3. match_phrase query

match_phrase 是另一种全文检索模式,与 match 模式不同的是:

  • match_phrase对字段作检索,有顺序要求
  • 允许有差异,可以通过 slop 指定

PUT test_index/doc/1
{
  "name": "New York"
}
GET test_index/_search
{
  "query": {
    "match_phrase": {
      # match_phrase 对单词顺序有要求,下面的条件将无法查询到结果,使用 match 可以
      "name": {
        "query": "York New",
      }
    }
  }
}

# 可以通过 slop 字段指明差异度,指明为2 表示可以有两处差异,下面的语句可以查询出上面创建的文档
GET test_search_index/_search
{
  "query": {
    "match_phrase": {
      "job": {
        "query": "York New",
        "slop": 2
      }
    }
  }
}
4. Query String query
  • 类似于 URISearch 的 q 查询
GET test_index/_search
{
  "query": {
    "query_string": {
      # 默认查询字段为 name
      # 查询 name 中包含 alfred 和 way 的文档
      "default_field": "name",
      "query": "alfred AND way"
    }
  }
}


GET test_search_index/_search
{
  "profile": true,
  "query": {
    "query_string": {
      # 指明查询字段,查询 name 和 job 字段中含有 alfred 或者 java 和 ruby 的文档
      "fields": ["name", "job"],
      "query": "alfred OR (java and ruby)"
    }
  }
}

上面通过 fields 指明字段列表时要注意其各个字段的数据类型要保持一致,否则会报错。

5. Simple query string

类似于 query string, 但是会忽略错误的查询语法,并且只支持一部分查询语法,注意一点:

  • 不能直接使用 AND、 OR、 NOT,他们会被当做字符串来处理,要用 +、 |、 - 代替。
# 必须包含 way, 可以包含 alfred
GET test_index/_search
{
  "profile": true,
  "query": {
    "simple_query_string": {
      # name 中包含 alfred 和 way 的文档
      "query": "alfred +way",
      "fields": ["name"]
    }
  }
}

三. Term Query

Term Query 将整个查询语句作为一个单词进行查询,不对查询语句做分词处理

GET test_index/_search
{
  "query": {
    "term": {
      "name": "New York"
    }
  }
}
GET test_index/_search
{
  "query": {
    "terms": {
      "name": [
      # 可以分开指定
      "New",
      "York"
      ]
    }
  }
}
2. range query

针对数值和日期的范围查询, 操作有:

  • gt 大于
  • gte 大于等于
  • lt 小于
  • lte 小于等于
 GET test_index/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}


GET test_search_index/_search
{
  "query": {
    "range": {
      "birth": {
        "gte": "1980-01-01",
        "lte": "2000-01-01"
      }
    }
  }
}

GET test_search_index/_search
{
  "query": {
    "range": {
      "birth": {
        # 灵活的日期计算方式
        "gte": "now-50y"
      }
    }
  }
}
复合查询

复合查询主要包含以下几类:

  • constant_score query:
  • bool: filter, must, must_not, should
  • dis_max
  • function_score
bool 查询

该查询有四种查询情况, 如图

这里写图片描述

GET index/doc/_search
{
  "query": {
    "bool": {
      "filter":[{}], # 支持数组
      "must":[{}],
      "must_not":[{}],
      "should":[{}]

    }
  }
}
  • filter 只查询符合条件的结果,不进行相关性算分,并且会有智能缓存,因此在不需要做相关性算分的时候推荐使用 filter
GET test_search_index/_search
{
  "query": {
    "bool": {
      "filter": {
          "term":{
            "name": "alfred"
          }
        }
      }
    }
}

# match contain
GET test_search_index/_search
{
  "query": {
    "bool": {
      # must 会影响相关性算分,
      "must": [
        {"term": {"username": "alfred"}},
        {"match":{"job": "java"}}
      ]
    }
  }
}


GET test_search_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "job": "java"
          }
        }
      ],
      "must_not": [
        {
          "match":{
            "job":"ruby"
          }
        }
      ]
    }
  }
}

GET test_search_index/_search
{
  "query": {
    "bool": {
      # 只包含 should 的时候,文档必须满足至少一个条件,
      # 可以通过 minimum_should_match 控制匹配的数量
      "should": [
        {"term": {"job": "java"}},
        {"term": {"job": "ruby"}},
        {"term": {"job": "specialist"}}
      ],
      "minimum_should_match": 2
    }
  }
}

如果结合 must 相同,不要求必须至少满足 should 中的一个条件,但如果满足的话,查询出的结果其相关性算分会高

count API 与_source
  • count 用来做计数,当只需要统计,不需要实际数据时使用,类似于 Django ORM 中的 count(),当只需要获取文档数不需要获取文档内容时使用
GET test_search_index/_count
{
  "query": {
    "match": {
      "username": "New York"
    }
  }
}
  • _source: 用来过滤要显示的字段,否则默认是返回所有字段的
# 指定返回字段
GET test_search_index/_search
{
  "_source": ["username", "age"]
}

# 匹配过滤
GET test_search_index/_search
{
  "_source": {
    "excludes": "*g*",
    "includes": "*er*"
  }
}  

以上就是 ElasticSearcb 中一些常用的查询 API 的使用,更多的内容还是需要参考官方文档: Search API 文档Query DSL 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值