Elasticsearch DSL QUERY

本文将主要介绍 Elasticsearch 的 DSL(Domain Special Language) 基本概念后用法。 根据 ElasticSearch v7.6 官方文档 Query DSL 整理而成。

概念

Elasticsearch 基于 JSON 提供了完整的查询 DSL 用来定义查询。可以把 DSL 查询当做是一种 抽象语法树 AST(Abstract Syntax Tree) 查询,由两种类型的语句组成。

Leaf query clauses

叶子查询语句,用于查询某一个特定字段的特定值,例如:查询关键字 match, term 和 range,这些查询可以单独使用。

Compound query clauses

组合查询语句,由叶子查询语句或者其他组合查询语句组合而成,用于构成复杂查询逻辑。其主要通过查询关键字 bool, dis_max 或 constant_score 来组合包装叶子查询语句

查询语句在查询上下文 (query context) 或者过滤上下文(filter context) 中有不同的表现

Query and filter context

相关性评分(relevance score)

默认情况下,ES 根据相关性评分来对查询的结果进行排序,用来表示查询结果和查询目标的匹配程度。

相关性评分是一个正的浮点数,在每条返回文档的元字段(meta-field) 中的 _score 字段值就是该条数据的相关性评分。评分越高,说明返回的文档的相关性越高。不同的查询类型的计算的相关性评分是不同的。

查询上下文(Query context)

在查询上下文中,查询语句所表达的意思类似于:”当前文档与查询语句所表达的意思的匹配度是多少”。除了判断文档是否匹配,查询语句还会计算相关评分,并在 _score 元字段中返回。

查询上下文是通过将查询语句传入 query 参数来实现的。

1
2
3
4
5
6
GET /_search
{
"query" : {
"match" : { "about" : "rock" }
}
}

过滤上下文(Filter context)

在过滤上下文中,查询语句锁表达的意思类似于:“当前文档与查询语句是否匹配”,只判断文档是否匹配,而不会去计算相关性评分。过滤上下文常用于过滤结构化的数据,例如:

  • 时间戳 timestamp 是否在时间区间 2019~2020 内
  • 文档的 status 字段值是否是 “published”

频繁使用的过滤上下文会被 ES 自动缓存,来提升查询速度。
过滤上下文是用过在查询语句中传入 filter 参数来实现的。例如: 在 bool 查询中的 filter 和 must_not 参数,constant_score 中的 filter 参数 和 聚合(aggregation) 中的 filter

1
2
3
4
5
6
7
8
9
10
POST /_search
{
"query": {
"bool": {
"filter": [
{ "range": { "age": {"lte": 30 }}}
]
}
}
}

例: 过滤语句和查询语句结合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /_search
{
"query": {
"bool": {
"must": [
{"match": {"about": "rock"}}
],
"filter":[
{ "range": { "age": {"lte": 30 }}}
]
}
}
}

组合查询 (Compound queries)

组合查询用户封装其他组合查询或者叶子查询,其一是可以合并查询的结果和相关性评分,其二是可以改变查询的行为,例如从查询上下文切换至过滤上下文。

用于组合查询的查询关键字,如下:

bool 查询

bool 查询是用于组合其他查询的一个关键字,其由一个或多个布尔查询子句组成。bool 参数如下

  • must: 选填,匹配的文档必须符合查询语句中表达的条件,在查询上下文中执行,影响相关性评分。如果 must 中包含多个查询语句,必须同时满足所有查询条件,相当于 and
  • filter: 选填,匹配的文档必须符合过滤语句中表达的条件,在过滤上下文中执行,不影响相关性评分。如果 must 中包含多个过滤语句,必须同时满足所有过滤条件。相当于 and
  • should: 选填,匹配的文档中必须符合所有查询条件中的一个或多个条件,在查询上下文中执行,影响相关性评分。相当于 or
  • must_not: 选填,匹配的文档中不能符合所有查询条件中表达的条件,在过滤上下文中执行,不影响 _score 值.

bool 查询采用 more-matches-is-better(匹配的条件越多越好)的策略,因此,每个匹配文档的相关性评分来自于不同查询语句(must 或者 should)的评分会相加之和。

使用 minimum_should_match

我们可以使用参数 minimum_should_match 来指定 should 查询中文档需要匹配的查询语句的条数或百分比。例如:should 中共包含 4 条查询语句,如果 minimum_should_match 值为 2 或 50%,这说明文档必须匹配其中的两条查询语句。

如果 bool 查询中只包含一种 should 查询语句,没有 must 或 filter 语句,minimum_should_match 默认值是 1,否则默认值是 0.

Boosting 查询

Boosting 查询返回匹配 positive 查询条件的文档,但是,如果又同时匹配 negative 查询,该文档的相关性评分将会减少。

我们可以使用 boosting 查询来在放回结果中,降级某些文档(使其排序靠后)而不是直接排除他们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GET /_search
{
"query": {
"boosting": {
"positive": {
"match": {
"about": "rock"
}
},
"negative": {
"match": {
"about": "albums"
}
},
"negative_boost" : 0.2
}
}
}

参数说明:

  • positive: 必填,需要放回的文档的查询条件。符合条件的文档会全部返回。
  • negative: 必填,用来减少相关性评分的查询条件。计算方法:将 positive 查询中获得的评分 乘以 negative_boost 的值
  • negative_value: 必填,0~1.0 直接的浮点数,用于降级加权。

constant_score query

constant_score 查询封装了 filter 查询,正如其名,返回的结果文档中,其相关性评分固定为一个常量,这个常量由参数 boost 决定。

1
2
3
4
5
6
7
8
9
POST /_search
{
"query": {
"constant_score": {
"filter": {"match": {"about": "rock"}},
"boost" : 1.2
}
}
}

参数:

  • filter: 必填,过滤条件,任何匹配查询条件的文档都会返回。过滤查询,不计算相关性评分
  • boost: 选填,浮点数,指定的相关性评分,默认值为 1.0

dis_max query(分离最大化查询)

Disjunction max 查询,返回匹配一个或多个查询条件的文档返回。如果返回的文档匹配多个查询条件,dis_max 查询将会取其中得分最高的查询,加上其他匹配项捆绑系数,作为文档相关性评分。

我们可以使用 dis_max 查询来实现需要不同 boost 因子的查询。

1
2
3
4
5
6
7
8
9
10
11
12
POST /_search
{
"query": {
"dis_max": {
"queries": [
{"match": {"about": "rock"}},
{"match": {"about": "albums"}}
],
"tie_breaker": 0.1
}
}
}

参数说明:

  • queries: 必填,查询条件数组,有一个或多个查询条件语句组成。返回匹配一条或多条查询语句的文档。如果文档匹配了多条查询语句,ES 将会使用其中相关性评分最高的查询的评分位置该文档的相关性评分。
  • tie_breaker: 选填,浮点数,取值 0 ~ 1.0 之间,默认 0。用于增加匹配多条查询语句的文档相关性评分。

tie_breaker 算法使用需满足某个文档匹配了多条查询语句的场景

1、取所有匹配的查询语句中相关性评分最高的评分: h_score
2、将 tie_breaker 值与所有匹配的其他查询语句(得分最高除外)的相关性评分相乘, 获得 t_scores
3、h_score 和 t_scores 所有值相加,获得 _score,作为文档的相关性评分

function_score query

function_score 查询 允许我们改变检索出来文档的相关性评分。使用 function_score 我们需要定义个查询语句和一个或多个函数。其中函数用于重新计算查询语句返回的文档的相关性得分。

详情介绍课参考文章通过Function Score Query优化Elasticsearch搜索结果, 或官方文档

全文检索(Full text queries)

全文检索提供了我们分析文本信息的能力。查询的字符所使用的分析器(analyzer)和创建索引的时候使用的是一样的。

全文检索的关键字有如下:

Intervals query

Intervals 查询使用一个或多个匹配规则组成,这些规则都是作用于某个特定的字段的。其主要功能是实现精确控制词在文档中出现的先后关系,实现了对 查询目标之间顺序、距离以及他们之间的包含关系灵活控制。该关键字有 es 7.0 中引入。

详细介绍参考 【elasticsearch 7.0 新特性之Intervals query](https://www.jianshu.com/p/39146f535bad), 或官方文档

match query

match 查询根据提供的文本,日期,布尔值来匹配文档。文本在查询之前会经过解析器(analyzes) 分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /_search
{
"query": {
"match": {
"about": {
"query": "rock"
}
}
}
}
or
POST /_search
{
"query": {
"match": {
"about": "rock"
}
}
}

match 一级参数 field: 必填,即需要查找的字段名

二级参数:

  • query: 必填,即需要在一级 field 字段中需要查找的值,值类型可为 text, number, boolean 或 date。match 查询在开始执行之前,提供的 text 类型的值会经过解析器(analyzes) 分析,因此,match 查询的 text 值不是精确匹配的。

  • analyzer: 选填, 类型string,指定解析器用于解析 query 字段的 text 类型值。默认使用建索引使用的解析器。

  • auto_generate_synonyms_phrase_query: 选填,bool,默认 true。是否自动生成短语查询
  • fuzziness: 选填,string,允许的最大编辑距离(edit distance)。编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.
  • max_expansions: 选填,integer,默认 0. 查询允许扩展的 terms(词组) 最大数量。
  • prefix_length: 选填,integer,默认 0. 用与 模糊匹配的最大前缀长度
  • transpositions: 选填, boolean, 默认 true. 是否模糊匹配时允许换位两个相邻的词(ab->ba)
  • fuzzy_rewrite: 选填, string, 指定查询重写的方法
  • lenient: 选填,boolean, 默认 false. 如果设置为true将导致基于格式的失败(例如向数字字段提供文本)被忽略
  • operator: 选填,枚举[OR, AND], 默认 OR. 假如查询的值为 capital of Hungary , operator=OR: 会被解释为 capital OR of OR Hungary. operator=AND: 会被解释成 capital AND of AND Hungary.
  • minimum_should_match: 选填,string。在所有查询条件中最小匹配的查询条件的条数或百分比
  • zero_terms_query: 选填,枚举[none, all], 默认 none. 如果查询条件为空时。none: 不返回文档。all: 返回所有文档,类似 match_all.

match_bool_prefix 查询

match_bool_prefix 查询内部将输入文本进过解析器(analyzes) 分离成多个 term(词)。除了最后一个词,其他词都执行 term 查询,最后一个词使用 prefix 查询。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET /_search
{
"query": {
"match_bool_prefix" : {
"about" : "I like c"
}
}
}

equals to

GET /_search
{
"bool": {
"should" : [
{"term": {"about": "I"}},
{"term": {"about": "like}},
{"prefix": {"about": "c"}}
]
}
}

match_phrase 查询

match_phrase 查询的目标文档,必须包含所提供的查询参数的所有词,而且每个词的顺序和提供的参数中一致。例如:

1
2
3
4
5
6
7
8
POST /_search
{
"query": {
"match_phrase": {
"about": "collect rock albums"
}
}
}

上例中能被匹配的文档必须满足一下条件:

1、about 字段中必须 collect、rock、albums 三个词全部都需要有
2、rock 的位置必须比 collect 的位置大 1
3、albums 的位置必须比 collect 的位置大 2

match_phrase_prefix

match_phrase_prefix 与 match_phrase 类似,不同点在于其参数值得最后一个词,必须作为前缀来处理。

1
2
3
4
5
6
7
8
POST /_search
{
"query": {
"match_phrase_prefix": {
"about": "collect rock a"
}
}
}

multi_match query

multi_match 查询允许一个查询值,匹配多个字段

1
2
3
4
5
6
7
8
9
POST /_search
{
"query": {
"multi_match": {
"query": "smith",
"fields": ["title", "*_name"] // 查询字段 title, 以_name 结尾的字段(例:first_name, last_name)
}
}
}

multi_match 查询类型

  • best_fields: 默认,所有字段都匹配一次,单最后使用相关性评分最高的字段作为该文档的相关性评分 (dis_max 可以实现同样效果)
  • most_fields: 所有字段匹配后的相关评分相加后作为该文档的相关性评分 (bool.should 可以实现同样效果)
  • cross_fields: 所有字段使用同一的解析器(analyzer or 分词器),将他们当成一个大字段处理
  • phrase: 使用 match_phrase 方式分别查询各个字段,使用相关性评分最高的
  • phrase_prefix:使用 match_phrase_prefix 方式分别查询各个字段,使用相关性评分最高的
  • bool_prefix: 使用 match_bool_prefix 方式分别查询各个字段,将获得相关性评分相加后作为其文档评分

query_string 查询

query_string 查询可以执行一个复杂的查询,它能跨多个字段进行查询(也可以无需指定字段),使用通配符进行查询。查询语句验证严格遵循查询语法,根据特定的操作符进行分词。

1
2
3
4
5
6
7
8
9
GET /_search
{
"query": {
"query_string" : {
"query" : "(climbing) OR (collect rock)",
"default_field" : "about"
}
}
}

参数说明:

  • query: 必填,string, 查询匹配的内容,有特定的查询语法
  • default_field: 选填 string. 如果未指定前缀字段,则为查询字词的默认字段。 默认为index.query.default_field索引设置,默认为 ,当值为 时,文档中的所有字段可以被查询和过滤
  • allow_leading_wildcard: 选填,boolean, 设置为 *或? 被允许作为第一个字符。 默认为true
  • analyze_wildcard: 选填,boolean, 默认情况下,不分析查询字符串中的通配符术语。 将此值设置为true,将尽力分析这些值
  • analyzer: 选填,string 用于分析查询字符串的分析器
  • auto_generate_phrase_queries: 选填,boolean, 是否自动生成短语查询,默认False
  • boost: 选填,float, 设置查询的提升值。 默认为1.0
  • default_operator: 选填,枚举[AND,OR] 假如查询的值为 capital of Hungary , operator=OR: 会被解释为 capital OR of OR Hungary. operator=AND: 会被解释成 capital AND of AND Hungary
  • enable_position_increments: 选填,boolean, 设置为true可在结果查询中启用位置增量。 默认为true
  • fields: 选填, []string。 指定想要查找的字段名列表
  • fuzziness:选填,string, 设置模糊查询的模糊性。 默认为AUTO
  • fuzzy_max_expansions: 选填,integer, 控制模糊查询将扩展到的术语数。 默认值为50
  • fuzzy_prefix_length: 选填,integer, 设置模糊查询的前缀长度。 默认值为0
  • fuzzy_transposition: 选填,boolean, 是否模糊匹配时允许换位两个相邻的词(ab->ba)
  • lenient: 选填,boolean, 如果设置为true将导致基于格式的失败(例如向数字字段提供文本)被忽略
  • max_determinized_states: 选填,interge, 限制允许创建多少个自动机状态regexp查询。 这防止了太难的(例如指数级的)正则表达式。 默认为10000
  • minimum_should_match: 选填,string, 用于控制在生成的布尔查询中应该匹配多少个叶子查询。 它可以是绝对值(2),百分比(30%)或两者的组合。
  • quote_analyzer: 选填,string, 指定引用文本的解析器, 默认为 search_quote_analyzer
  • quote_field_suffix: 选填,string,引文的前缀
  • phrase_slop: 选填,integer, 设置短语的默认斜率。 如果为零,则需要精确的短语匹配。 默认值为0
  • rewrite: 选填,string, 指定重写查询的方法
  • time_zone: 选填,string, 要应用于与日期相关的任何范围查询的时区

query 查询语法

1、查询 status 字段包括 active, status:active
2、查询 title 字段包含 quick 或者 brown, title:(quick OR brown)
3、查询 author 字段包括准确的短语 “john smith”, author:”John Smith”
4、查询 first name 字段是否包含 Alice, first\ name:Alice, 空格需要反斜杠转义
5、查询字段 book.title, book.date, book.content 包含 quick 或 brown, book.*:(quick OR brown), 注意 在 * 之前需要 反斜杠
6、查询 title 字段是否有 non-null 值, exists:title

simple_query_string 查询

simple_query_string 查询与 query_string 查询功能类似,但是,如果输入的查询语句语法不合法,其不会抛出不合法的错误,而是直接忽略不合法的部分。

1
2
3
4
5
6
7
8
9
10
POST /_search
{
"query": {
"simple_query_string" : {
"query": "\"fried eggs\" +(eggplant | potato) -frittata",
"fields": ["title^5", "body"],
"default_operator": "and"
}
}
}

simple_string_query 查询参数和 string_query 查询参数类似,有query, fields, default_operator,
all_fields, 等。

其 query 参数的查询语法与 string_query 是不同的。

  • +:表示 AND 操作符
  • |: 表示 OR 操作符
  • -: 相当于 NOT 操作符
  • “: 用于将多个 token 封装成短语查询
  • : 用于表示某个前缀查询, pre_\
  • ( ): 提升优先级
  • ~N: 在单词之后表示编辑距离, 短语之后表示短语倾斜旅

进一步详细介绍参考官方文档

Term-level 查询

Term-level 查询可以用于精确地查找结构化的查询。例如查询 id, 价格,时间区间等。
与全文检索的查询不同

与全文检索类型的检索类型不同,term-level 查询不会使用解析器(analyzer), 而是使用精确匹配查询的字段。

Term-level 查询类型

exists 查询

exists 查询用于查询特点字段是否存在被索引的值。
一个字段是否被索引可以通过以下条件判断

  • 在 JSON 中字段的值为 null 或者 [] 不被索引
  • 在 mapping(索引管理)中设置了该字段 “index”: false, 该字段不被索引
  • 字段值长度超过 mapping 设置的 ignore_above 值,该字段不被索引
  • 字段值不符合格式(malformed)的,且 mapping 中设置了 ignore_malformed, 该字段不被索引
1
2
3
4
5
6
7
8
POST /_search
{
"query": {
"exists": {
"field": "education"
}
}
}

field 字段一下场景也会会索引

  • 空字符串, 例如 “” 或者 “-“
  • 数组中包含 null 和其他值, 例如:[null, “foo”]
  • 在 mapping 中设置的 null-value

fuzzy 查询

fuzzy 查询:根据编辑距离(edit distance) 来查询字段值值相似的文档。为了找出相似的词,fuzzy 查询会在指定的编辑距离内生成-组可能的词,然后去精确匹配查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /_search
{
"query": {
"fuzzy": {
"about": {
"value": "ro",
"fuzziness": "AUTO",
"max_expansions": 50,
"prefix_length": 0,
"transpositions": true,
"rewrite": "constant_score"
}
}
}
}

一级参数: field, 必填,object, 想要搜索的字段
二级参数,field 参数:

  • value: 必填,string, 想要在 field 字段检索的词
  • fuzziness: 选填,string, 最大的编辑距离设置, 首选选择 “AUTO”
  • max_expansions: 选填,integer, 生成用于查询的相似词的数量,默认 50
  • prefix_length: 选填,integer, 在生成查询相似词时,不能修改的前缀位数,默认 0
  • rewrite: 选填,string, 用于重写查询的方法。

ids 查询

ids 查询: 根据文档 _id 字段进行查询,返回匹配文档

1
2
3
4
5
6
7
8
POST /_search
{
"query": {
"ids": {
"values": ["1", "3"]
}
}
}

prefix 查询

prefix 查询: 根据指定前缀查询特定字段的词,返回匹配的文档
例如,查询 last_name 字段以 sm 开头的词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /_search
{
"query": {
"prefix": {
"user": {
"value": "sm"
}
}
}
}
or
{
"query": {
"prefix": {
"user": "sm"
}
}
}

一级参数: field 字段名,用于查询的字段名
二级参数: value: 想要在 field 字段查询的值;rewrite: 重新查询的方法

range 查询

range 查询: 根据指定的范围查询某一字段,返回匹配文档

1
2
3
4
5
6
7
8
9
10
11
12
POST /_search
{
"query": {
"range": {
"age": {
"gte": 20,
"lt": 30,
"boost": 2.0
}
}
}
}

一级参数: field, 目标查询字段
二级参数:

  • gt: 选填, 大于
  • gte: 选填, 大于等于
  • lt: 选填,小于
  • lte: 选填,小于等于
  • format: 选填,string,时间格式化,用于日期搜索
  • relation: 选填, string, 定义区间查询的方式。INTERSECTS(默认), CONTAINS, WITHIN(??)
  • time_zone: 选填,string, 设置时区
  • boost: 选填,float, 用于相加或减少相关性评分,默认 1.0

regexp 查询

regexp 查询:使用正则表达式查询特定字段,返回匹配文档

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /_search
{
"query": {
"regexp": {
"user": {
"value": "k.*y",
"flags" : "ALL",
"max_determinized_states": 10000,
"rewrite": "constant_score"
}
}
}
}

一级参数: field, 目标查询字段
二级参数 for field:

  • value: 必填,string,正则表达式,尊重正则表达式语法,默认情况下表达式限制为 1000 个字符
  • flags: 选填,string, 选择正则查询模式
  • max_determinized_states: 选填,integer,查询最大自动状态机(automaton states) ,默认 10000
  • rewrite: 选填, string, 查询重写方法

term 查询

term 查询:在特定字段中,去精确匹配某个词的方式进行查询,返回匹配文档

1
2
3
4
5
6
7
8
{
"query": {
"term": {
"last_name": "rock",
"boost": 1.0
}
}
}

一级参数: field,目标查询字段
二级参数:

  • value: 必填,string, 在目标字段需要查询的词,精确匹配,包括空格,大小写
  • boost: 选填,float, 用于相加或减少相关性评分,默认 1.0

note: 应该避免使用 term 查询去查询 text 类型的字段。

terms 查询

terms 查询:根据提供的多个词(term), 在特定字段中有一个或多个词能精确匹配,则返回文档
terms 查询和 term 查询原则一样,区别在于 terms 提供了一组词

1
2
3
4
5
6
7
8
9
POST /_search
{
"query": {
"terms": {
"last_name": ["rock", "smith"],
"boost": 1.0
}
}
}

terms 查询参数与 term 查询一样。

terms_set 查询

terms_set 查询:根据提供的多个词,在特定的字段中进行精确匹配,如果匹配数量不少于指定的最小数量,则返回文档。
terms_set 与 terms 查询类似,区域在于 terms_set 指定了匹配的最小数量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建记录
PUT /_doc/2?refresh
{
"name": "Jason Response",
"programming_languages": ["java", "php"],
"required_matches": 2
}

POST /_search
{
"query": {
"terms_set": {
"programming_languages": {
"terms": ["c++", "java", "php"],
"minimum_should_match_field": "required_matches"
}
}
}
}

一级参数: field,目标查询字段
二级参数:

  • terms: 必填, []string, 用于匹配的多个词
  • minimum_should_match_field: 选填,string, 指定数字类型字段,例如 required_matches
  • minimum_should_match_script: 选填,string, 用于计算最低匹配数量的通用脚本,适用于当terms 数组中词数量动态变化的时候,具体见How to use the minimum_should_match_script parameter

type 查询

type 查询:根据 mapping 中设置的类型进行查询,将被移除。

wildcard 查询

wildcard 查询:根据通配符查询词,返回匹配文档

1
2
3
4
5
6
7
8
9
10
11
12
POST /_search
{
"query": {
"wildcard": {
"last_name": {
"value": "ki*y",
"boost": 1.0,
"rewrite": "constant_score"
}
}
}
}

一级参数:field, 查询目标字段
二级参数 for field:

  • value: 必填,string, 使用通配符构成的值,?匹配一个字符,*匹配0或多个字符,
  • boost: 选填,float, 用于相加或减少相关性评分,默认 1.0
  • rewrite: 选填, string, 查询重写方法

Geo(空间) 查询

ES 支持两种类型的 geo 数据, 1、geo_point:支持lat/lon 2、geo_shape: 支持多点,线,圆,多边形,类多边形(multi-polygons) 等。

查询关键字如下:

geo_bounding_box 查询

geo_bounding_box 查询: 允许使用包围盒的方式来查询对应的文档
例:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
创建索引 
PUT /my_locations
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
}
// 插入数据
PUT /my_locations/_doc/1
{
"pin": {
"location": {
"lat": 40.12,
"lon": -71.34
}
}
}
// 查询
POST /my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}

geo_bounding_box 查询参数(必须在 filter 上下文使用?)

  • _name: 必填,string, 用于过滤的字段名,例如:pin.location
  • validation_method: 选填,查询模式 STRICT(默认): 严格模式校验坐标格式,COERCE: 尝试将错误坐标格式转为正确的,IGNORE_MALFORMED: 容忍错误的坐标格式
  • type: 选填, 枚举(indexed, memory), 定义过滤是操作是在 memory 还是 indexed

_name 下二级参数: top_left 左上坐标, bottom_right 右下坐标

note: geo_bounding_box 允许的坐标格式

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// lat lon as properties
{
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}

// format in [lon, lat]
{
"geo_bounding_box": {
"pin.location": {
"top_left": [-74.1, 40.73],
"bottom_right": [-71.12, 40.01]
}
}
}
// format in lat, lon
{
"geo_bounding_box": {
"pin.location": {
"top_left": "40.73, -74.1",
"bottom_right": "40.01, -71.12"
}
}
}
// Well-Known Text
{
"geo_bounding_box": {
"pin.location": {
"wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)
}
}
}
// GeoHash
{
"geo_bounding_box": {
"pin.location": {
"top_left": "dr5r9ydj2y73",
"bottom_right": "drj7teegpus6"
}
}
}

// Vertices
{
"geo_bounding_box": {
"pin.location": {
"top": 40.73,
"left": -74.1,
"bottom": 40.01,
"right": -71.12
}
}

geo-distance 查询

geo-distance 查询:指定一个坐标点和距离,返回距离辐射之内的坐标的文档
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /_search
{
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "200km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}

geo_distance 参数

  • distance: 必填,string, 指定距离,可用单位
  • distance_type: 选填,string, 指定距离计算方式,arc(默认):考虑了地球弧度, plane: 不准确,计算速度快
  • _name: 必填,string, 指定过滤的字段名
  • validation_method: 选填,查询模式 STRICT(默认): 严格模式校验坐标格式,COERCE: 尝试将错误坐标格式转为正确的,IGNORE_MALFORMED: 容忍错误的坐标格式

NOTE:查询中接受的坐标格式和 geo_bounding_box 一直

geo-polygon 查询

geo-polygon 查询:提供多个坐标点,返回落在坐标点内的文档
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /_search
{
"query": {
"bool": {
"must": {
"match_all": []
},
"filter": {
"pin.locations": {
"points": [
{"lat" : 40, "lon" : -70},
{"lat" : 30, "lon" : -80},
{"lat" : 20, "lon" : -90}
]
}
}
}
}
}

geo_polygon 参数:

  • _name: 必填,string, 指定过滤的字段名
  • validation_method: 选填,查询模式 STRICT(默认): 严格模式校验坐标格式,COERCE: 尝试将错误坐标格式转为正确的,IGNORE_MALFORMED: 容忍错误的坐标格式

NOTE: 其他表示坐标格式化方式, 参见官方文档

geo_shape 查询

geo_shape 查询: 根据提供的地图图形,以一定规则查询文档。使用 geo_shape 查询需要被查询的字段使用 geo_shape 的字段类型。
例如:

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
// 创建索引
PUT /my_locations
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
// 插入数据
PUT /my_locations/_doc/1
{
"area": {
"name": "Wind & Wetter, Berlin, Germany",
"location": {
"type": "point",
"coordinates": [13.400544, 52.530286]
}
}
}

PUT /my_locations/_doc/2
{
"area": {
"name": "Berlin, Germany"
"location": {
"type": "envelope",
"coordinates" : [[13.0, 53.0], [14.0, 52.0]]
}
}
}

例如:定义一个矩形的空间区域,找到再该区域内的文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /my_locations/area/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates" : [[13.0, 53.0], [14.0, 52.0]]
},
"relation": "within"
}
}
}
}
}
}

geo_shape 查询中 relation 参数取值:

  • INTERSECTS: 默认, 查询几何相交的所有文档
  • WITHIN: 返回查询内几何范围内的所有文档
  • CONTAINS: 返回包含查询几何的所有文件
  • DISJOINT: 返回不在几何辐射范围内的文档?

geo_shape 还支持一种称为 pre-indexed shape(预索引形状)的查询。我们可以预先定义好一个空间图形,并未这个图形定义一个逻辑名称,这样每次查询就不需要都提供坐标。详见官方文档