- 常用 DSL 关键字
- 查询上下文
- 相关度评分:_score
- 源数据:_source
- 数据源过滤器
- query 和 filter 上下文
- 相关性评分 (relevance scores)
- query 的上下文
- filter 的上下文
- 关于 query 和 filter 上下文的例子
- 全文查询 (full text query)
- intervals 查询
- 请求示例
intervals
的顶级参数match
(匹配) 规则参数prefix
(前缀) 规则参数wildcard
(通配符) 规则参数fuzzy
(模糊) 规则参数all_of
(全部) 规则参数any_of
(任意一个) 规则参数filter
(过滤) 规则参数- 注意
- filter 示例
- 脚本过滤器 (script filters)
- 最小限度(minimization)
- match(匹配查询):匹配包含某个 term 的子句
match
的顶级参数<field>
的参数- 注意
- 简短请求示例
- match 查询是如何工作的?
- match 查询中的模糊性(fuzziness)
- 零词项查询 (zero terms query)
- 截止频率 (cutoff frequency)
- 同义词 (synonyms)
- match_bool_prefix(布尔前缀匹配查询)
- 参数
- match_phrase(短语匹配查询)
- match_phrase_prefix(短语前缀匹配查询)
- 请求示例
match_phrase_prefix
的顶级参数<field>
的参数- 注意
- 使用匹配短语前缀查询进行搜索自动完成(search autocompletion)
- match_all:匹配所有结果的子句
- multi_match(多字段匹配查询)
fields
和 字段增强(per-field boosting)multi_match
查询的类型:best_fields
- most_fields
phrase
和phrase_prefix
cross_fields
cross_field
和分析(analysis)
tie_breaker
bool_prefix
- 例如
- 多字段匹配(multi_match)查询
fields
和 字段增强(per-field boosting)
multi_match
查询的类型:best_fields
most_fields
phrase
和phrase_prefix
cross_fields
cross_field
和分析(analysis)tie_breaker
bool_prefix
- query_string(查询字符串查询)
- 下面是几个例子:
- 查询所有
- 分页
- 精准匹配 exact value
- _all 搜索 相当于在所有有索引的字段中检索
- 请求示例
query_string
的顶级参数- 注意事项
- 查询字符串语法
- 字段名称(field names)
- 通配符
- 正则表达式
- 模糊性(Fuzziness)
- 避免混合使用模糊性和通配符
- 邻近搜索 (proximity searches)
- 范围 (ranges)
- 增强 (boosting)
- 布尔运算符 (boolean operators)
- 分组 (grouping)
- 保留字符
- 空格和空查询 (whitespaces and empty queries)
- 避免对嵌套文档使用
query_string
查询 - 搜索多个字段
- 多字段搜索的附加参数
- 同义词与
query_string
查询 minimum_should_match
是如何工作的minimum_should_match
如何处理多个字段的匹配minimum_should_match
如何处理跨字段搜索- 注意
- 允许执行昂贵的查询
- 简单查询字符串(simple_query_string)查询
- 请求示例
simple_query_string
的顶级参数- 注意
- 简单查询字符串语法
- 限制查询中可以使用的运算符
- 有效值
fields
参数中的通配符和按字段增强- 同义词
- 下面是几个例子:
- 精准查询 Term query
- term:匹配和搜索词项完全相等的结果
- term 和 match_phrase 的区别
- terms:匹配和搜索词项列表中任意项匹配的结果
- range:范围查找
- term:匹配和搜索词项完全相等的结果
- 过滤器 Filter
- Filter 缓存机制
- intervals 查询
- 复合查询 (compound queries)
- Bool 查询
- 使用
minimum_should_match
- 用
bool.filter
评分 - 使用命名查询(named queries)查看哪子句匹配
- 例子
- should 与 must 或 filter 一起使用
- minimum_should_match
- 使用
- Boosting查询
- 请求示例
- 用于
Boosting
的顶级参数
- constant_score 查询
constant_score
的顶级参数- dis_max (disjunction max) 查询
- 请求示例
dis_max
的顶级参数
- function_score (函数评分) 查询
- 脚本评分 (Script score)
- 权重 (weight)
- 随机 (random)
- 字段值因子 (field value factor)
- 衰减函数 (decay functions)
- 支持的衰减函数
- 多值字段 (multi-values fields)
- 详细示例
- 正态衰减,关键字
gauss
- 指数衰减,关键字
exp
- 线性衰减,关键字
linear
- 衰减函数支持的字段
- 如果一个字段缺失,怎么办?
- Bool 查询
- 联结查询 (joining queries)
- 嵌套(nested)查询
- 请求示例
- 准备一个索引
- 查询示例
nested
的顶级参数- 注意
- 多级嵌套查询 (multi-level nested queries)
- 请求示例
- has_child 查询
- 请求示例
- 创建索引
- 查询示例
has_child
的顶级参数- 注意
- 排序
- 请求示例
- has_parent 查询
- 请求示例
- 创建索引
- 查询示例
has_parent
的顶级参数- 注意
- 排序
- 请求示例
- parent_id 查询
- 请求示例
- 创建索引
- 查询示例
parent_id
的顶级参数
- 注意
- 允许执行昂贵的查询
- 请求示例
- 跨度查询(span)
- span_containing 查询
- field_masking_span 查询
- span_first 查询
- span_multi 查询
- span_near 查询
- span_not 查询
- span_or 查询
- span_term 查询
- span_within 查询
- 词级查询 (term-level query)
- 词项级别查询的类型
- exists 查询
- 请求示例
exists
的顶级参数- 注意
- 查找缺少索引值的文档
- 模糊查询 (fuzzy query)
- 请求示例
- 一个简单的例子
- 一个使用高级参数的例子
fuzzy
的顶级参数<field>
的参数- 注意
- 请求示例
- ids
- 请求示例
ids
的顶级参数
- 前缀查询 (prefix query)
- 请求示例
prefix
的顶级参数<field>
的参数- 注意
- 短请求格式的示例
- 提高前缀查询的速度
- 允许执行昂贵的查询
- 范围查询 (range query)
- 请求示例
range
的顶级参数<field>
的参数- 注意
- 在
text
和keyword
类型的字段上使用range
查询 - 在
date
类型的字段上使用range
查询
- 在
- 日期计算及舍入
- 使用
time_zone
参数的查询示例
- 正则表达式查询 (regexp query)
- 请求示例
regexp
的顶级参数<field>
的参数- 注意
- 允许执行昂贵的查询
- term 查询
- 请求示例
term
的顶级参数<field>
的参数- 注意
- 避免在
text
字段上使用term
查询
- 避免在
- terms 查询
- 请求示例
terms
的顶级参数- 注意
- 高亮
terms
查询
- 高亮
- 词项查找(terms lookup)
- 词项查找(terms lookup)的参数
- 词项查找(terms lookup)示例
- terms_set 查询
- 请求示例
- 创建索引
- 查询示例
terms_set
的顶级参数<field>
的参数- 注意
- 如何使用
minimum_should_match_script
参数? - 使用
minimum_should_match_script
的查询示例
- 如何使用
- 请求示例
- 通配符查询(wildcard query)
- 请求示例
wildcard
的顶级参数<field>
的参数- 注意
- 允许昂贵的查询
minimum_should_match
参数rewrite
参数- 有效值
rewrite
参数的性能考量
- 正则表达式语法
- 保留字符
- 标准运算符
- 可选的运算符
- 有效值
- 不支持的运算符
- 专业的查询 (Specialized queries)
- geo(地理位置查询)
- 形状查询
- 嵌套(nested)查询
DSL 是 Domain Specific Language 的缩写,指的是为特定问题领域设计的计算机语言。这种语言专注于某特定领域的问题解决,因而比通用编程语言更有效率。
在 ElasticSearch(ES)中,DSL 指的是 ElasticSearch Query DSL,一种以 JSON 形式表示的查询语言。通过这种语言,用户可以构建复杂的查询、排序和过滤数据等操作。这些查询可以是全文搜索、分面/聚合搜索,也可以是结构化的搜索。
常用 DSL 关键字
- query: 用于包含查询使用到的语法
- match_all: 最简单的查询,获取索引所有数据,类似搜索 *。如:”query”:{“match_all”:
- bool: 复合查询,可以包含多个查询条件,主要有(must,must_not,should)
- must: 用于包含逻辑与查询条件,即所有查询条件都满足才行
- must_not: 用于包含逻辑非查询条件,即不包含所有查询的条件数据
- should: 用于包含逻辑或查询条件,即其中有一个条件满足即可
- filter: 与 must 一样,包含的所有条件都要满足,但不会参与计算分值,查询速度上会提升不少
- match: 匹配查询,用于匹配指定属性数据,也可以匹配时间,IP 等特殊数据 注意: match 匹配不会解析通配符,匹配的效果受到索引属性类型影响,如果索引属性设置了分词,那么 match 匹配也会分词匹配,他也不解析”“,但可以设置逻辑关系来处理
- operator: 匹配逻辑关系,默认是 or,可设置为 and,这样可达到精确匹配的效果
- query_string: 使用查询解析器来解析查询内容,如 port:80 AND server:http。注意:此类型请求有很多选项属性,可以设置一些特殊的行为
- term: 查找包含在反向索引中指定的确切术语的文档
- terms: 筛选具有匹配任何条件的字段,如”terms” :
- range: 将文档与具有特定范围内的字段相匹配。Lucene 查询的类型依赖于字段类型,对于字符串字段,即 TermRangeQuery,而对于 number/date 字段,查询是一个数字的范围。如:”range”:{“port”:{“gte”:10,”lte”:20,”boost”:2.0}}
- gte: 大于或等于
- gt: 大于
- lte: 小于或等于
- lt: 小于
- boost: 设置查询的 boost 值,默认值为 1.0
- exists: 返回在原始字段中至少有一个非空值的文档,注意:”“,”-“这些都不算是空值
- prefix: 匹配包含带有指定前缀字段的字段(没有分析),前缀查询映射到 Lucene 前缀查询,如:”prefix” : { “user” : “ki” },查询 user 数据前缀为 ki 的 doc
- wildcard: 匹配具有匹配通配符表达式的字段(未分析)的文档。支持 (*通配符) 是匹配任何字符序列(包括空的序列)和 (?通配符) 它匹配任何一个字符。注意,这个查询可能比较慢,因为它需要迭代多个术语。为了防止非常慢的通配符查询,一个通配符项不应该从通配符开始,或者?通配符查询映射到 Lucene 通配符查询。如:”wildcard” :
- regexp: regexp 查询允许您使用正则表达式术语查询,意味着 ElasticSearch 将把 regexp 应用到该字段的标记器所产生的词汇,而不是该字段的原始文本。regexp 查询的性能严重依赖于所选择的正则表达式,通配符往往会降低查询性能。如:”regexp”:
- fuzzy: 模糊查询使用基于 Levenshtein 编辑距离的相似性。如:”fuzzy” :
- type: 过滤文档匹配所提供的文档/映射类型。如:”type”:
- ids: 过滤只具有提供的 id 的文档。注意:这个查询使用了_uid字段,类型是可选的,可以省略,也可以接受一组值。如果没有指定类型,那么将尝试在索引映射中定义的所有类型。如:”ids”:{ “type” : “my_type”,”values” : [“1”,”4”,”100”] }。
- highlight: 允许在一个或多个字段中突出显示搜索结果,基于 lucene plain highlighter。在默认情况下,高亮显示会将高亮显示的文本包装在 *and* ,可以通过设置 pre_tags 与 post_tags 来自定义,如:”highlight”:{ “pre_tags” : [““], “post_tags” : [““], “fields” : {“_all”:{}} }
- pre_tags: 自定义包含搜索关键字的前缀
- post_tags: 自定义包含搜索关键字的后缀
- fields: 用于指定要高亮的属性,_all 表示所以属性都需要高亮,如:”fields”:{ “_all” : {} },也可以指定具体属性 “fields”:{ “app” : {} },也可以给每个属性单独指定设置 “fields”:{ “app” : {“fragment_size” : 150, “number_of_fragments” : 3} }
- highlight_query: 可以通过设置 highlight_query 来突出显示搜索查询之外的查询,通常,最好将搜索查询包含在 highlight_query 中。如:”highlight_query”:{ “bool”:{“must”:[{“query_string”:{“query”:app:apache,”analyze_wildcard”:True,”all_fields”:True}}]} }
- fragment_size: 用于指定高亮显示时,碎片的长度,如果过短,高亮内容会被切分为多个碎片。默认情况下,当使用高亮显示的内容时,碎片大小会被忽略,因为它会输出句子,而不管它们的长度
- number_of_fragments 用于指定高亮显示时,碎片的数量,如果指定为 0,那么就不会产生任何片段
- from: 可以通过使用 from 和 size 参数来对结果进行分页,from参数指定您想要获取的第一个结果的偏移量
- size: 可以通过使用 from 和 size 参数来对结果进行分页,size参数指定要返回结果的最大数量
- sort: 允许在特定的字段上添加一个或多个排序,排序是在每个字段级别上定义的,用特殊的字段名来排序,然后根据索引排序进行排序,如”sort”: [ { “date”: { “order”: “desc” } } ],desc 降序,asc 升序
- aggs: aggs 主要用于分类集合,可以将查询的数据按指定属性进行分类集合统计.如:”aggs”:{ “deviceType”:{ “terms”:{ “field”:”deviceType”, “size”:6 } } }
- field: 用于指定要分类的属性名称
- size: 用于指定分类集合的数量,即只集合前 N 名
查询上下文
使用 query 关键字进行检索,倾向于相关度搜索,故需要计算评分。搜索是ElasticSearch最关键和重要的部分。
在查询上下文中,一个查询语句表示一个文档和查询语句的匹配程度。无论文档匹配与否,查询语句总能计算出一个相关性分数在 _score
字段上。
相关度评分:_score
相关度评分用于对搜索结果排序,评分越高则认为其结果和搜索的预期值相关度越高,即越符合搜索预期值,默认情况下评分越高,则结果越靠前。在 7.x 之前相关度评分默认使用 TF/IDF 算法计算而来,7.x 之后默认为 BM25。
源数据:_source
source 字段包含索引时原始的 JSON 文档内容,字段本身不建立索引(因此无法进行搜索),但是会被存储,所以当执行获取请求是可以返回 source 字段。
虽然很方便,但是 source 字段的确会对索引产生存储开销,因此可以禁用 source 字段,达到节省存储开销的目的。可以通过以下接口进行关闭。
PUT my_index
{"mappings": {"_source": {"enabled": false}}
}
但是需要注意的是这么做会带来一些弊端,_source 禁用会导致如下功能无法使用:
- 不支持 update、update_by_query 和 reindex API。
- 不支持高亮。
- 不支持 reindex、更改 mapping 分析器和版本升级。
总结:在禁用 source 之前,应该仔细考虑是否需要进行此操作。如果只是希望降低存储的开销,可以压缩索引比禁用 source 更好。
数据源过滤器
例如,假设你的应用只需要获取部分字段(如 "name" 和 "price" ),而其他字段(如 "desc" 和 "tags" )不经常使用或者数据量较大,导致传输和处理这些额外的数据会增加网络开销和处理时间。在这种情况下,通过设置includes和excludes可以有效地减少每次请求返回的数据量,提高效率。例如:
PUT product
{"mappings": {"_source": {"includes": ["name", "price"],"excludes": ["desc", "tags"]}}
}
Including: 结果中返回哪些 field。
Excluding: 结果中不要返回哪些 field,不返回的 field 不代表不能通过该字段进行检索,因为元数据不存在不代表索引不存在,Excluding 优先级比 Including 更高。
需要注意的是,尽管这些设置会影响搜索结果中 _source 字段的内容,但并不会改变实际存储在ElasticSearch 中的数据。也就是说,"desc" 和 "tags" 字段仍然会被索引和存储,只是在获取源数据时不会被返回。
在 mapping 中定义这种方式不推荐,因为 mapping 不可变。我们可以在查询过程中使用 _source 指定返回的字段,如下:
GET product/_search
{"_source": {"includes": ["owner.*", "name"],"excludes": ["name", "desc", "price"]},"query": {"match_all": {}}
}
ElasticSearch 的 _source
字段在查询时支持使用通配符(wildcards)来包含或排除特定字段。使得能够更灵活地操纵返回的数据。
关于规则,可以参考以下几点:
- *:匹配任意字符序列,包括空序列。
- ?:匹配任意单个字符。
- [abc]: 匹配方括号内列出的任意单个字符。例如,[abc]将匹配"a", "b", 或 "c"。
请注意,通配符表达式可能会导致查询性能下降,特别是在大型索引中,因此应谨慎使用。
query 和 filter 上下文
相关性评分 (relevance scores)
默认情况下,ElasticSearch 根据 相关性评分(relevance score) 对匹配到的搜索结果进行排序,这个分数用来衡量每个文档与查询的匹配程度。
相关性分数是一个正浮点数,在 search API 返回结果的 _score
元字段中。 _score
越高,文档的相关性就越强。 虽然每种查询类型都可以不同地计算关联分数,但分数计算也取决于查询子句是在 query 上下文中运行还是在 filter 上下文中运行。
query 的上下文
在 query 上下文中,查询子句回答“此文档与此查询子句的匹配程度如何?”。 除了决定文档是否匹配之外,查询子句还计算文档的相关性得分(在元字段 _score
中显示)。
query 上下文在查询子句传递给 query
参数(例如 search API 中的 query
参数)时生效。
filter 的上下文
在 filter 上下文中,查询子句回答“此文档与此查询子句匹配吗?”。 答案是简单的"是"或"否"--不会计算分数。 filter 上下文主要用于过滤结构化数据,比如:
- 这个 timestamp 是否落在 2015 - 2016 范围内?
- status 字段是否设置为"published"?
Elasticearch 会自动缓存经常使用的 filter,以提高性能。
每当查询子句传递给 filter 参数时,过滤器上下文就生效,例如bool
查询中的filter
或must_not
参数,constant_score
查询中的filter
参数,或者filter
聚合。
关于 query 和 filter 上下文的例子
下面是一个在 search
API 中的 query 和 filter 上下文中使用的查询子句的示例。 该查询将匹配满足以下所有条件的文档:
- 字段
title
包含单词search
。 - 字段
content
包含单词ElasticSearch
。 - 字段
status
完全匹配published
。 - 字段
publish_date
包含从 2015-1-1 之后(大于)的日期。
GET /_search
{"query": { "bool": { "must": [{ "match": { "title": "Search" }},{ "match": { "content": "ElasticSearch" }}],"filter": [ { "term": { "status": "published" }},{ "range": { "publish_date": { "gte": "2015-01-01" }}}]}}
}
query
参数指示查询上下文。bool
和两个match
子句用于 query 上下文,这表示它们用于对每个文档的匹配程度进行评分。filter
参数指示 filter 上下文。 其中term
和range
子句用于 filter 上下文。 它们将过滤掉不匹配的文档,但不会影响匹配文档的得分。
在 query 上下文中为查询计算的分数是一个单精度浮点数;它们的有效精度只有24位。 超过有效精度的分数值将被转换为失去精度的浮点数。
在 query 上下文中使用查询子句,用于应该参与计算匹配文档得分的条件(即文档匹配的好坏),而所有其他查询子句(不需要计算得分的)应该放在 filter 上下文中。
全文查询 (full text query)
全文查询使你能够搜索已分析的文本字段 (analyzed text fields),如 email 的正文。 使用在 索引(indexing, 动词) 期间应用于字段的同一个 分析器(analyzer) 来处理查询字符串。
该组中的查询包括:
intervals
查询
一种全文查询,允许对匹配项的排序和接近程度进行细粒度控制。match
查询
用于执行全文查询的标准查询,包括 fuzzy(模糊) 匹配 和 phrase(短语) 或 proximity(邻近) 查询。match_bool_prefix
查询
创建一个bool
查询,将每个 词项(term) 作为一个term
查询进行匹配,但最后一个词项除外(它作为prefix
查询进行匹配)。match_phrase
查询
类似于match
查询,但用于匹配精确的短语(phrase) 或 单词近似(proximity)匹配。match_phrase_prefix
查询
类似于match_phrase
查询,但是对最后一个单词进行通配符搜索。multi_match
查询
match
查询的多字段(multi-field)版本。common
词项查询
更专业的查询,更倾向于不常用的单词。query_string
查询
支持简练的 Lucene 查询字符串语法,允许你在单个查询字符串中指定 AND|OR|NOT 条件 和 多字段搜索。 仅供专家级别的用户使用。simple_query_string
查询
query_string
语法的一个更简单、更健壮的版本,适合直接向用户公开。
全文检索是 ElasticSearch 的核心功能之一,它可以高效地在大量文本数据中寻找特定关键词。
在 ElasticSearch 中,全文检索主要依靠两个步骤:"分析"(Analysis)和"查询"(Search)。
- 分析: 当你向 ElasticSearch 索引一个文档时,会进行"分析"处理,将原始文本
数据转换
成称为 "tokens" 或 "terms" 的小片段。这个过程可能包括如下操作:- 切分文本(Tokenization)
- 将所有字符转换为小写(Lowercasing)
- 删除常见但无重要含义的单词(Stopwords)
- 提取词根(Stemming)
- 查询: 当执行全文搜索时,查询字符串也会经过类似的分析过程,然后再与已经分析过的索引进行比对,找出匹配的结果并返回。
ElasticSearch 提供了许多种全文搜索的查询类型,例如:
- Match Query: 最基本的全文搜索查询。
- Match Phrase Query: 用于查找包含特定短语的文档。
- Multi-Match Query: 类似 Match Query,但可以在多个字段上进行搜索。
- Query String Query: 提供了丰富的搜索语法,可以执行复杂的、灵活的全文搜索。
intervals 查询
根据匹配 词项(term) 的顺序和接近程度返回文档。
intervals
查询使用匹配规则(matching rules),这些规则由一小组定义构成。 然后将这些规则应用于指定 字段(field)
中的 词项(term)。
这些定义产生的最小区间序列跨越了文本主体中的词项(term)。 这些 间隔(interval) 可以由父源进一步组合和过滤。
请求示例
下面这个 intervals
搜索返回字段 my_text
中包含 my favorite food
的文档,且 my favorite food
后面紧跟着 hot water
或 cold porridge
。
这个搜索会匹配字段 my_text
的值为 my favorite food is cold porridge
的文档,但不会匹配 when it's cold my favorite food is porridge
。
POST _search
{"query": {"intervals" : {"my_text" : {"all_of" : {"ordered" : true,"intervals" : [{"match" : {"query" : "my favorite food","max_gaps" : 0,"ordered" : true}},{"any_of" : {"intervals" : [{ "match" : { "query" : "hot water" } },{ "match" : { "query" : "cold porridge" } }]}}]}}}}
}
intervals
的顶级参数
<field>
(必需的,规则(rule)对象) 你想搜索的字段。该参数的值是一个规则(rule)对象,用于根据匹配的词项(term)、顺序(order)和接近性(proximity)来匹配文档。可用的规则(rule)包括:match
(匹配)prefix
(前缀)wildcard
(通配符)fuzzy
(模糊)all_of
(全部)any_of
(任意一个)
match
(匹配) 规则参数
match
匹配规则匹配 已分析的文本(analyzed text)。
query
(必需的,string) 你想在指定的<field>
中搜索的文本.max_gaps
(可选, integer) 匹配词项之间的最大位置数。比这更远的词项不会被视为匹配。默认值为-1
。如果未指定或设置为-1
,则匹配没有宽度限制。 如果设置为0
,这些词项必须相邻出现。ordered
(可选,boolean) 如果为true
,匹配的词项必须按其指定的顺序出现。默认值为false
。analyzer
(可选,string) 用于分析query
中的 词项(term) 的 analyzer(分析器)。 默认为<field>
的顶级 分析器(analyzer)。filter
(可选,interval filter 规则对象) 一个可选的 interval filter。use_field
(可选,string) 如果指定了,则匹配此 field 而不是顶级<field>
的间隔。 使用 搜索分析器(search analyzer) 分析该字段中的词项(term)。 这将允许你跨多个字段进行搜索,就好像它们是同一个字段; 例如,你可以将相同的文本索引到 带词干(stemmed) 和 不带词干(unstemmed) 的字段,并在不带词干的字段附近搜索带词干的 词元(token)。
prefix
(前缀) 规则参数
prefix
(前缀) 规则匹配以指定字符集开头的词项。 这个前缀最多可以扩展到匹配 128 个词项。 如果前缀匹配超过 128 个词项,ElasticSearch 将返回一个错误。 可以在字段映射中使用 index-prefixes
选项来避免这个限制。
prefix
(必需的,string) 你希望在顶级<field>
中查找的词项的开始字符。analyzer
(可选,string) 用于归一化prefix
的 analyzer(分析器)。 默认为<field>
的顶级 分析器(analyzer)。use_field
(可选,string) 如果指定了,则匹配此 field 而不是顶级<field>
的间隔。如果没有单独指定一个analyzer
,会使用字段的 搜索分析器(search analyzer) 对prefix
进行归一化。
wildcard
(通配符) 规则参数
wildcard
规则使用一个通配符模式匹配词项。 这个模式最多可以扩展到匹配 128 个词项。 如果前缀匹配超过 128 个词项,ElasticSearch 将返回一个错误。
pattern
(必需的,string) 用于查找匹配的词项的通配符模式。该参数支持两个通配符操作符:?
,它匹配任意的单个字符*
,它可以匹配零个或多个字符,包括一个空字符避免模式以*
或?
开头。 这可能会增加查找匹配词项所需的迭代次数,并降低搜索性能。analyzer
(可选,string) 用于归一化pattern
的 analyzer(分析器)。 默认为<field>
的顶级 分析器(analyzer)。use_field
(可选,string) 如果指定了,则匹配此 field 而不是顶级<field>
的间隔。如果没有单独指定一个analyzer
,会使用字段的 搜索分析器(search analyzer) 对pattern
进行归一化。
fuzzy
(模糊) 规则参数
fuzzy
规则在由 fuzziness 定义的编辑距离内匹配与所提供的词项相似的词项。 如果模糊扩展匹配超过 128 项,ElasticSearch 将返回错误。
译者注: 请先了解 "编辑距离" (edit distance) 的有关概念。
term
(必需的,string) 要匹配的词项。prefix_length
(可选,integer) 创建扩展时,开头字符保持不变的个数。默认为0
。transpositions
(可选,boolean) 指示编辑是否包括两个相邻字符的换位(ab → ba)。默认为true
。fuzziness
(可选,string) 匹配时允许的最大编辑距离。 默认值为auto
。 有关有效值和更多信息请参考 fuzziness。analyzer
(可选,string) 用于对term
进行归一化的 analyzer(分析器)。 默认为顶级<field>
的分析器(analyzer)。use_field
(可选,string) 如果指定了,则匹配此 field 而不是顶级<field>
的间隔。如果没有单独指定一个analyzer
,会使用字段的 搜索分析器(search analyzer) 对term
进行归一化。
all_of
(全部) 规则参数
all_of
规则返回跨越其他规则组合的匹配。
intervals
(必需的,规则对象数组) 要组合的规则数组。 所有规则都必须在文档中产生一个匹配项,以便整个源文件匹配。max_gaps
(可选,integer) 匹配词项之间的最大位置数。由规则产生的间隔比这更远则不会被认为是匹配的。默认值为-1
。如果未指定或设置为-1
,则匹配没有宽度限制。 如果设置为0
,这些词项必须相邻出现。ordered
(可选,boolean) 如果为true
,匹配的词项必须按其指定的顺序出现。默认值为false
。filter
(可选,interval filter 规则对象) 用于过滤返回的间隔的规则。
any_of
(任意一个) 规则参数
any_of
规则返回由其任意一个子规则产生的间隔。
intervals
(必需的,规则对象的数组) 要匹配的规则的数组。filter
(可选,interval filter 规则对象) 用于过滤返回的间隔的规则。
filter
(过滤) 规则参数
filter
规则根据 查询(query) 返回间隔。 有关示例请参考 filter 示例。
after
(可选,query 对象) 用于返回filter
规则中某个间隔之后的间隔的查询。 (原文: Query used to return intervals that follow an interval from the filter rule.)before
(可选,query 对象) 用于返回filter
规则中某个间隔之前发生的间隔的查询。contained_by
(可选,query 对象) 用于从filter
规则中返回间隔所包含的间隔的查询。containing
(可选,query 对象) 用于返回包含filter
规则中的间隔的间隔的查询。not_contained_by
(可选,query 对象) 用于返回filter
规则中的间隔不包含的间隔的查询。not_containing
(可选,query 对象) 用于返回不包含filter
规则中间隔的间隔的查询。not_overlapping
(可选,query 对象) 用于返回与filter
规则中的间隔不重叠的间隔的查询。overlapping
(可选,query 对象) 用于返回与filter
规则中的间隔重叠的间隔的查询。script
(可选,脚本对象) 用于返回匹配文档的脚本。 这个脚本必须返回一个布尔值,true
或false
。 有关示例请参考 脚本过滤器(script filters)。
注意
filter 示例
下面这个例子包含一个 filter
规则。 它返回的文档中,单词 hot
和 porridge
的位置相差不超过 10 个,且中间没有单词 salty
:
POST _search
{"query": {"intervals" : {"my_text" : {"match" : {"query" : "hot porridge","max_gaps" : 10,"filter" : {"not_containing" : {"match" : {"query" : "salty"}}}}}}}
}
脚本过滤器 (script filters)
可以使用脚本根据间隔的开始(start)位置、结束(end)位置和内部间隙(gap)计数来过滤间隔。 下面这个 filter
脚本将 interval
变量与 start
、end
和 gaps
方法一起使用:
POST _search
{"query": {"intervals" : {"my_text" : {"match" : {"query" : "hot porridge","filter" : {"script" : {"source" : "interval.start > 10 && interval.end < 20 && interval.gaps == 0"}}}}}}
}
最小限度(minimization)
intervals 查询总是最小化间隔,以确保查询可以线性时间运行。 这有时会导致令人惊讶的结果,尤其是在使用 max_gaps
限制或 filter 时。 例如,以下面的查询为例,搜索包含在短语 hot porridge
中的 salty
:
POST _search
{"query": {"intervals" : {"my_text" : {"match" : {"query" : "salty","filter" : {"contained_by" : {"match" : {"query" : "hot porridge"}}}}}}}
}
该查询与包含短语 hot porridge is salty porridge
的文档不匹配,因为 hot porridge
的匹配查询返回的间隔仅覆盖该文档中的前两个词项,并且这些词项与覆盖 salty
的间隔不重叠。
另一个需要注意的限制是包含重叠子规则的 any_of
规则的情况。 特别是,如果其中一个规则是另一个规则的严格 前缀(prefix),那么更长的规则永远不会匹配,这在与 max_gaps
结合使用时会导致意外。 考虑下面这个查询,搜索 the
, 后面紧接着 big
或 big bad
,然后后面再紧接着 wolf
:
POST _search
{"query": {"intervals" : {"my_text" : {"all_of" : {"intervals" : [{ "match" : { "query" : "the" } },{ "any_of" : {"intervals" : [{ "match" : { "query" : "big" } },{ "match" : { "query" : "big bad" } }] } },{ "match" : { "query" : "wolf" } }],"max_gaps" : 0,"ordered" : true}}}}
}
与直觉相反,这个查询与文档 the big bad wolf
不 匹配, 因为中间的 any_of
规则只产生 big
的区间 - big bad
的区间比 big
的区间长, 同时从相同的位置开始,因此被最小化。 在这些情况下,最好重写查询,以便所有选项都显式地显示在顶层:
POST _search
{"query": {"intervals" : {"my_text" : {"any_of" : {"intervals" : [{ "match" : {"query" : "the big bad wolf","ordered" : true,"max_gaps" : 0 } },{ "match" : {"query" : "the big wolf","ordered" : true,"max_gaps" : 0 } }]}}}}
}
match(匹配查询):匹配包含某个 term 的子句
返回与提供的文本、数字、日期或布尔值相 匹配(match) 的文档。 匹配前会分析提供的文本。
match
查询是执行全文搜索的标准查询,包括一些 模糊(fuzzy) 匹配选项。
match
的顶级参数
<field>
(必需的, object) 你想搜索的字段。
<field>
的参数
query
(必需的) 你希望在提供的<field>
中查找的文本(text)、数字(number)、布尔值(bool)或日期(date)。match
查询会在执行搜索前 analyzes 任何提供的文本。 这意味着match
查询可以在text
字段中搜索已分析的 词元(token),而不是精确的 词项(term)。analyzer
(可选, string) analyzer(分析器) 用于将query
中的文本转换为 词元(token)。 默认为映射到<field>
的 索引时使用的分析器。 如果没有映射分析器,则使用索引的默认分析器。auto_generate_synonyms_phrase_query
(可选, boolean) 如果为true
,将自动为 多词项同义词(multi-term synonyms) 创建 match phrase(短语匹配) 查询。 默认值为true
。有关示例请参考 在match查询中使用同义词。fuzziness
(可选, string) 匹配时允许的最大编辑距离。 可用的值及更多信息请参考 模糊性(fuzziness)。 有关示例请参考 match 查询中的模糊性。max_expansions
(可选, integer) 查询可以扩展到的最大 词项(term) 数。默认值为50
。prefix_length
(可选, integer) 模糊匹配的起始字符保持不变的分数。默认值为0
。fuzzy_transpositions
(可选, boolean) 如果为true
,模糊匹配的编辑包括两个相邻字符的交换(ab → ba)。默认值为true
。fuzzy_rewrite
(可选, string) 用于重写查询的方法。 可用的值及更多信息请参考rewrite
参数。如果参数fuzziness
的值不是0
,默认情况下,match
查询使用的rewrite
方法是top_terms_blended_freqs_${max_expansions}
。lenient
宽容的
(可选, boolean) 如果为true
,则忽略基于格式的错误,例如为 numeric 字段提供 text 格式的query
值。 默认值为false
。operator
(可选, string) 用于解释query
值中文本的布尔逻辑。有效值有:OR
(默认值) 例如,查询值capital of Hungary
被解释为capital OR of OR Hungary
。AND
例如,查询值capital of Hungary
被解释为capital AND of AND Hungary
。minimum_should_match
(可选, string) 要返回的文档必须匹配的最小子句数。 可用的值及更多信息请参考minimum_should_match
参数。zero_terms_query
(可选, string) 指示如果analyzer
删除所有 词元(token) (例如使用stop
过滤器时),是否不返回任何文档。有效值有:none
(默认值) 如果analyzer
删除所有 词元(token),则不返回任何文档。all
返回所有文档, 与match_all
查询类似。有关示例请参考 零词项查询(zero terms query)。
注意
简短请求示例
可以通过组合 <field>
和 query
参数来简化 match 查询语法。例如:
GET product/_search
{"query": {"match": {"name": "xiaomi nfc phone"}}
}
上面的搜索语句,只要文档的 "name" 字段包含 "xiaomi"、"nfc" 或者 "phone" 中的任何一个词,就会被视为匹配。
match 查询是如何工作的?
match
查询属于 boolean
类型。 这意味着对所提供的文本进行分析,并且分析过程从所提供的文本中构造一个 boolean 查询。 参数 operator
可以设置为 or
或 and
,以控制 boolean 子句(默认为 or
)。 可以使用 minimum_should_match
参数设置要匹配的可选 should
子句的最小数量。
下面是一个带有 operator
参数的示例:
GET /_search
{"query": {"match" : {"message" : {"query" : "this is a test","operator" : "and"}}}
}
可以设置 analyzer
来控制使用哪个分析器对文本执行分析过程。 它默认为字段的显式映射定义,或默认的搜索分析器。
可以将参数 lenient
设置为 true
,以忽略由数据类型不匹配导致的异常,例如尝试使用 text 查询字符串查询 numeric 字段。 默认值为 false
。
match 查询中的模糊性(fuzziness)
fuzziness
(模糊性) 允许基于被查询的字段类型进行模糊匹配。 有关允许的设置,请参考 模糊性。
在这种情况下,可以设置 prefix_length
和 max_expansions
来控制模糊处理过程。 如果设置了模糊选项,查询将使用 fuzzy_rewrite
参数允许的 top_terms_blended_freqs_${max_expansions}
作为其 重写方法(rewrite method) 去控制如何重写查询。
默认情况下允许模糊换位(ab
→ ba
),但可以通过将 fuzzy_transpositions
设置为 false
来禁用。
模糊匹配不适用于具有同义词的词项(term),也不适用于分析过程在同一位置产生多个词元(token)的情况。 在底层,这些词项(temr)被扩展为一个混合了词项频率的特殊同义词查询,它不支持模糊扩展。
GET /_search
{"query": {"match" : {"message" : {"query" : "this is a testt","fuzziness": "AUTO"}}}
}
零词项查询 (zero terms query)
如果所使用的分析器像 stop
过滤器一样删除查询中的所有词元(token),那么默认行为是根本不匹配任何文档。 为了改变这种情况,可以使用 zero_terms_query
选项,它接受 none
(默认值) 和 all
(对应于 match_all
查询)。
GET /_search
{"query": {"match" : {"message" : {"query" : "to be or not to be","operator" : "and","zero_terms_query": "all"}}}
}
截止频率 (cutoff frequency)
在 7.3.0 中废弃。
此选项可以省略,因为 匹配(match) 可以有效地跳过文档块,而无需任何配置,前提是不跟踪命中的总数。
匹配查询支持 cutoff_frequency
,它允许指定一个绝对或相对的文档频率,其中高频词项被移到可选的子查询中,并且只有在 or
运算符时有一个低频(低于截止值)词项匹配 或 and
运算符时所有低频词项都匹配 时才被计分。
该查询允许在运行时动态处理 stopwords
(停止词) ,它是独立于域(domain)的,并且不需要停止词文件。 它防止对高频词项进行评分/迭代,并且仅在更重要/更低频率的词项匹配文档时才考虑这些词项。 然而,如果所有查询项都高于给定的 cutoff_frequency
,则该查询会自动转换为纯的结合(and
)查询,以确保快速执行。
cutoff_frequency
的值,在 [0, 1) 范围内时是一个相对于文档总数的值,而在 >= 1.0 时是一个绝对值。
下面这个示例显示了一个全部由 停止词(stopword) 组成的查询:
GET /_search
{"query": {"match" : {"message" : {"query" : "to be or not to be","cutoff_frequency" : 0.001}}}
}
cutoff_frequency
选项在每个分片级别上执行。 这意味着当在文档数很少的测试索引上试用它时,你应该遵循“相关性被破坏)”中的建议。
同义词 (synonyms)
match
查询通过 synonym_graph 词元过滤器支持多词项的同义词扩展。 当使用这个过滤器时,解析器为每个多词项的同义词创建一个短语(phrase)查询。 例如,同义词 "ny, new york"
将产生:
(ny OR ("new york"))
也可以用连接词来匹配多个词项同义词:
GET /_search
{"query": {"match" : {"message": {"query" : "ny city","auto_generate_synonyms_phrase_query" : false}}}
}
上面的例子创建了一个 boolean 查询:
(ny OR (new AND york)) city
它匹配带有词项 ny
或连接词 new AND york
的文档。 默认情况下,参数 auto_generate_synonyms_phrase_query
设置为 true
。
match_bool_prefix(布尔前缀匹配查询)
match_bool_prefix
查询分析它的输入内容,并根据这些词项构造一个 bool
查询。 除最后一个词项外,每个词项都用于 term
查询。 最后一个词项用于 prefix
查询。 match_bool_prefix
查询像这样:
GET /_search
{"query": {"match_bool_prefix" : {"message" : "quick brown f"}}
}
其分析后产生的词项quick
、brown
和 f
类似于下面的 bool
查询:
GET /_search
{"query": {"bool" : {"should": [{ "term": { "message": "quick" }},{ "term": { "message": "brown" }},{ "prefix": { "message": "f"}}]}}
}
match_bool_prefix
查询和 match_phrase_prefix
查询一个重要的区别是:match_phrase_prefix
查询将其词项作为短语进行匹配,而 match_bool_prefix
查询可以在任何位置匹配其词项。 上面的 match_bool_prefix
查询示例可以匹配包含quick brown fox
的字段,但也可以匹配 brown fox quick
。 它还可以匹配任何位置出现的包含词项quick
、词项 brown
及以 f
开头的词项的字段。
参数
默认情况下,将使用查询的字段在其映射中定义的分析器去分析match_bool_prefix
查询的输入文本。 可以使用 analyzer
参数配置一个不同的搜索(时使用的)分析器:
GET /_search
{"query": {"match_bool_prefix" : {"message": {"query": "quick brown f","analyzer": "keyword"}}}
}
match_bool_prefix
查询支持 match
查询 中描述的minimum_should_match
和 operator
参数,将设置应用于构造的 bool
查询。 在大多数情况下,构造的 bool
查询中的子句数将是通过分析查询文本产生的词项数。
fuzziness
、prefix_length
、max_expansions
、fuzzy_transpositions
和 fuzzy_rewrite
参数可以应用于除了最后一个词项之外的所有词项构建的 term
子查询。 它们对为最后一个词项构建的 prefix 查询没有任何影响。
match_phrase(短语匹配查询)
match_phrase
是 ElasticSearch 中的一种全文查询类型,它用于精确匹配包含指定短语的文档。match_phrase 查询需要字段值中的单词顺序与查询字符串中的单词顺序完全一致。
match_phrase
查询分析文本,并根据分析的文本创建一个 phrase
查询。例如:
GET /_search
{"query": {"match_phrase" : {"message" : "this is a test"}}
}
短语查询以任意顺序匹配最多 slop
个词项(这个 slop 可配置,默认为 0)。 颠倒顺序的词项的 slop 为 2。
可以设置 analyzer
来控制使用哪个分析器对文本执行分析过程。 它默认为字段的显式映射定义,或默认的搜索分析器。
GET /_search
{"query": {"match_phrase" : {"message" : {"query" : "this is a test","analyzer" : "my_analyzer"}}}
}
该查询还接受 zero_terms_query
,如 match
查询 中所述。
match_phrase_prefix(短语前缀匹配查询)
返回包含所提供文本中的单词的文档,这些单词在文档中的出现顺序与所提供的文本相同。 所提供文本的最后一个词项被视为 prefix(前缀),匹配以该单词开头的任何词项。
请求示例
以下搜索将返回 message
字段中包含以 quick brown f
开头的短语的文档。
这个搜索将匹配字段 message
的值为 quick brown fox
或 two quick brown ferrets
的,但是不会匹配 the fox is quick and brown
。
GET /_search
{"query": {"match_phrase_prefix" : {"message" : {"query" : "quick brown f"}}}
}
match_phrase_prefix
的顶级参数
<field>
(必需的, object) 你想搜索的字段。
<field>
的参数
query
(必需的, string) 您希望在提供的<field>
中查找的文本。在执行搜索之前,match_phrase_prefix
查询会将任何提供的文本 analyze(分析) 为 词元(token)。 该文本的最后一个词项被视为prefix(前缀),匹配以该词项开头的任何单词。analyzer
(可选, string) analyzer(分析器) 用来将query
中的文本转换为 词元(token)。 默认为映射到<field>
的 [索引时使用的分析器(index-time analyzer)。 如果没有映射分析器,则使用索引的默认分析器。max_expansions
(可选, integer)query
值的最后一个提供的词项将扩展到的最大词项数。默认值为50
。slop
(可选, integer) 匹配词元(token)之间允许的最大位置数。默认为0
。颠倒顺序的词项的 slop 为2
。zero_terms_query
(可选, string) 指示如果analyzer
删除所有 词元(token) (例如使用stop
过滤器时),是否不返回任何文档。有效值有:none
(默认值) 如果analyzer
删除所有 词元(token),则不返回任何文档。all
返回所有文档, 与match_all
查询类似。
注意
使用匹配短语前缀查询进行搜索自动完成(search autocompletion)
虽然很容易设置,但使用 match_phrase_prefix
查询进行搜索自动完成有时会产生令人困惑的结果。
例如,考虑查询字符串 quick brown f
。 这个查询的工作原理是用 quick
和 brown
创建一个短语查询(也就是说,词项 quick
必须存在,并且后面必须跟有词项 brown
)。 然后,它查看已排序的词项字典,查找以 f
开头的前50个词项语,并将这些词项添加到短语查询中。
问题是,前50个词项可能不包括词项 fox
,因此将找不到短语 quick brown fox
。 这通常不是问题,因为用户会继续输入更多的字母,直到他们要找的单词出现。
有关 输入即搜索(search-as-you-type) 的更好解决方案,请参阅 完成建议(completion suggester) 和 search_as_you_type
字段类型。
match_all:匹配所有结果的子句
match_all
是 ElasticSearch 中的一个查询类型,它匹配所有文档,不需要任何参数。
GET product/_search
{"query": {"match_all": {}}
}
上面的语句等价于:
GET /product/_search
这个查询将会返回索引中的所有文档。这通常用于在没有特定搜索条件时获取所有的文档,或者与其他查询结合使用(如过滤器)。
需要注意,由于 match_all
查询可能返回大量的数据,所以一般在使用时都会与分页(pagination)功能结合起来,这样可以控制返回结果的数量,避免一次性加载过多数据导致的性能问题。例如,你可以使用 from
和 size
参数来限制返回结果:
GET /_search
{"query": {"match_all": {}},"from": 10,"size": 10
}
multi_match(多字段匹配查询)
multi_match查询是 ElasticSearch 中用来在多个字段上执行全文查询的功能。它接受一个查询字符串和一组需要在其中执行查询的字段列表
multi_match查询建立在
match` 查询的基础上,以允许 多字段(multi-field) 查询:
GET /_search
{"query": {"multi_match" : {"query": "this is a test", "fields": [ "subject", "message" ] }}
}
- 要查询的字符串。
- 要查询的字段。
fields
和 字段增强(per-field boosting)
可以使用通配符指定字段名称,比如:
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","fields": [ "title", "*_name" ] }}
}
- 查询
title
、first_name
和last_name
字段。
单个字段可以用脱字符号(^
)来增强:
GET /_search
{"query": {"multi_match" : {"query" : "this is a test","fields" : [ "subject^3", "message" ] }}
}
- 字段
subject
的重要性是message
的3
倍。
如果未指定fields
,则multi_match
查询默认使用index.query.default_field
索引设置,该设置又默认为*
。*
提取映射中符合条件查询的所有字段,并过滤元数据字段。 然后将所有提取的字段组合起来构建一个查询。
一次可以查询的字段数量是有限制的。 它由indices.query.bool.max_clause_count
搜索设置 定义的,默认为 1024。
multi_match
查询的类型:
multi_match
查询在内部执行的方式取决于参数 type
,该参数可设置为:
参数 | 含义 |
---|---|
best_fields |
(默认) 查找与任何字段匹配的文档,但使用最佳字段的 _score 。参见 best_fields 。 |
most_fields |
查找与任何字段匹配的文档,并合并每个字段的 _score 。参见 most_fields 。 |
cross_fields |
用相同的 analyzer 处理字段,就好像它们是一个大字段。 在 任何 字段中查找每个单词。 参见 cross_fields 。 |
phrase |
对每个字段运行 match_phrase 查询,并使用最佳字段(best field)的 _score 。 参见 phrase 和 phrase_prefix 。 |
phrase_prefix |
对每个字段运行 match_phrase_prefix 查询,并使用最佳字段(best field)的 _score 。 参见 phrase和 phrase_prefix`。 |
bool_prefix |
在每个字段上创建 match_bool_prefix 查询,并组合每个字段的 _score 。 参见 bool_prefix 。 |
best_fields
best_fields
类型在搜索同一字段中最容易找到的多个单词时最有用。 例如,一个字段里的“brown fox”比一个字段里的“brown”和另一个字段里的“fox”更有意义。
best_fields
类型为每个字段生成一match
查询,并将它们包裹在一个 dis_max
查询中,以找到单个最佳匹配字段。 比如下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "brown fox","type": "best_fields","fields": [ "subject", "message" ],"tie_breaker": 0.3}}
}
在执行时会被转换为:
GET /_search
{"query": {"dis_max": {"queries": [{ "match": { "subject": "brown fox" }},{ "match": { "message": "brown fox" }}],"tie_breaker": 0.3}}
}
通常,best_fields
类型使用单个最佳匹配字段的分数,但如果指定了tie_breaker
,则它会按如下方式计算分数:
- 最佳匹配字段的分数
- 给所有其他匹配的字段加上
tie_breaker * _score
此外,接受analyzer
、boost
、operator
、minimum_should_match
、fuzziness
、lenient
、prefix_length
、max_expansions
、rewrite
、zero_terms_query
、cutoff_frequency
、auto_generate_synonyms_phrase_query
及fuzzy_transpositions
,如 match 查询 中所述。
operator
和minimum_should_match`` ``best_fields
和most_fields
类型是以字段为中心(field-centric)的,它们为每个字段生成一个match
查询。 这意味着operator
和minimum_should_match
参数分别应用于每个字段,这可能不是你想要的。
以下面这个查询为例:
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","type": "best_fields","fields": [ "first_name", "last_name" ],"operator": "and" }}
}
- 所有词项必须都出现。
该查询按如下方式执行:(+first_name:will +first_name:smith)
| (+last_name:will +last_name:smith)
换句话说,所有词项必须出现在一个字段中,文档才能匹配。
更好的解决方案请参考cross_fields
。
most_fields
当查询包含以不同方式分析的相同文本的多个字段时,most_fields
类型最有用。 例如,主字段可能包含同义词(synonyms)、词干(stemming)和不带发音符号(diacritics)的词项。 第二个字段可能包含原始的(original)词项(term),第三个字段可能包含 shingles(不知道该怎么翻译)。 通过组合所有三个字段的分数,我们可以将尽可能多的文档与主字段匹配,但使用第二个和第三个字段将最相似的结果推到列表的顶部。
下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "quick brown fox","type": "most_fields","fields": [ "title", "title.original", "title.shingles" ]}}
}
在执行时会被转换为:
GET /_search
{"query": {"bool": {"should": [{ "match": { "title": "quick brown fox" }},{ "match": { "title.original": "quick brown fox" }},{ "match": { "title.shingles": "quick brown fox" }}]}}
}
每个 match
子句的得分相加,然后除以 match
子句的数量。
此外,接受analyzer
、boost
、operator
、minimum_should_match
、fuzziness
、lenient
、prefix_length
、max_expansions
、rewrite
、zero_terms_query
及 cutoff_frequency
,如 match 查询 中所述,但是 请参见 operator 和 minimum_should_match。
phrase
和 phrase_prefix
phrase
和 phrase_prefix
类型的行为类似于best_fields
,但是它们使用 match_phrase
或 match_phrase_prefix
查询而不是 match
查询。
下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "quick brown f","type": "phrase_prefix","fields": [ "subject", "message" ]}}
}
在执行时会被转换为:
GET /_search
{"query": {"dis_max": {"queries": [{ "match_phrase_prefix": { "subject": "quick brown f" }},{ "match_phrase_prefix": { "message": "quick brown f" }}]}}
}
此外,还接受 match 中所述的 analyzer
、boost
、lenient
及 zero_terms_query
,以及 match phrase 中介绍的 slop
。 phrase_prefix
类型还接受 max_expansions
。
phrase
,phrase_prefix
和fuzziness
参数fuzziness
不能与phrase
和phrase_prefix
一起使用。
cross_fields
cross_fields
类型对于多个字段should(应该) 匹配的结构化文档特别有用。 例如,当在 first_name
和 last_name
字段查询“Will Smith”时,最佳匹配可能是一个字段中有“Will ”,另一个字段中有“Smith”。
这听起来像是
most_fields
的工作,但是那个方法有两个问题。
第一个问题是operator
和minimum_should_match
是按字段应用的,而不是按词项应用的(见上面的解释)。
第二个问题与相关性有关:first_name
和last_name
字段中不同的词频可能会产生意外的结果。
例如,假设我们有两个人:“Will Smith“ 和 “Smith Jones“。 “Smith“ 作为 姓(last name) 是很常见的(因此不太重要),但是“Smith“作为 名(first name) 是很少见的(因此非常重要)。
如果我们搜索“Will Smith“,文档“Smith Jones”可能会出现在更匹配的“Will Smith”之上,因为first_name:smith
的分数已经超过了first_name:will
加上last_name:smith
的组合分数。
处理这些类型的查询的一种方法是简单地将 first_name
和 last_name
字段索引到单个full_name
字段中。当然,这只能在索引时完成。
cross_field
类型试图通过采用*以词项为中心(term-centric)*的方法在查询时解决这些问题。 它首先将查询字符串分析成单个词项,然后在任何字段中查找每个词项,就好像它们是一个大字段一样。
像下面这样的一个查询
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "first_name", "last_name" ],"operator": "and"}}
}
会被执行为:
+(first_name:will last_name:will)
+(first_name:smith last_name:smith)
换句话说,所有词项 必须出现在至少一个字段中,文档才能匹配。 (将这与 用于 best_fields
和 most_fields
的逻辑进行比较。)
这解决了两个问题中的一个。 不同词频的问题通过 混合(blending) 所有字段的词频以消除差异来解决。
实际上,first_name:smith
将被视为与last_name:smith
+ 1 具有相同的频率。 这将使 first_name
和 last_name
的匹配项具有可比较的分数,last_name
有一点优势,因为它是最有可能包含smith
的字段。
请注意,cross_fields
通常只对 boost
都为 1
的短字符串字段有用。 否则 boost、词频和长度归一化会以这样的一种方式影响分数,以至于词项统计数据的混合不再有意义。
如果你通过 Validate API 运行上述查询,它将返回如下解释:
+blended("will", fields: [first_name, last_name])
+blended("smith", fields: [first_name, last_name])
此外,还接受 analyzer
、boost
、operator
、minimum_should_match
、lenient
、zero_terms_query
及 cutoff_frequency
,如 match 查询 中所述。
cross_field
和分析(analysis)
cross_field
类型只能在具有相同分析器的字段上以词项为中心(term-centric)的模式下工作。 如上例所示,具有相同分析器的字段被分组在一起。 如果有多个组,它们将与一个 bool
查询组合在一起。
例如,如果字段 first
和 last
具有相同的分析器,加上 first.edge
和 last.edge
都使用 edge_ngram
分析器,则下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "Jon","type": "cross_fields","fields": ["first", "first.edge","last", "last.edge"]}}
}
将被执行为:
blended("jon", fields: [first, last])
| (
blended("j", fields: [first.edge, last.edge])
blended("jo", fields: [first.edge, last.edge])
blended("jon", fields: [first.edge, last.edge])
)
换句话说,first
和 last
将被分组在一起并被视为单个字段,first.edge
and last.edge
将被分组在一起并被视为单个字段。
拥有多个组是可以的,但是当与 operator
或 minimum_should_match
结合使用时,它可能会遇到与most_fields
或 best_fields
相同的问题。
可以很容易地将该查询重写为两个单独的 cross_fields
查询与一个 bool
查询的组合,并将 minimum_should_match
参数应用于其中一个查询:
GET /_search
{"query": {"bool": {"should": [{"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "first", "last" ],"minimum_should_match": "50%" }},{"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "*.edge" ]}}]}}
}
will
或smith
必须出现在first
或last
字段中
通过在查询中指定analyzer
参数,可以强制将所有字段归入同一组。
GET /_search
{"query": {"multi_match" : {"query": "Jon","type": "cross_fields","analyzer": "standard", "fields": [ "first", "last", "*.edge" ]}}
}
- 对所有字段使用
standard
分析器。
它将被执行为:
blended("will", fields: [first, first.edge, last.edge, last])
blended("smith", fields: [first, first.edge, last.edge, last])
tie_breaker
默认情况下,每个按词项 blended
(混合的) 查询将使用组中任何字段返回的最佳分数,然后将这些分数相加得到最终分数。 参数 tie_breaker
可以更改按词项 blended
(混合的) 查询的默认行为。 它接受:
参数 | 含义 |
---|---|
0.0 |
取单个最佳分数(默认)。(比如从first_name:will 和last_name:will 中取最佳分数) |
1.0 |
将分数相加。(比如把first_name:will 和last_name:will 的分数相加) |
0.0 < n < 1.0 |
将单个最佳分数加上 tie_breaker 乘以其他匹配字段中的每个分数。 |
cross_fields
和fuzziness
参数fuzziness
不能与cross_fields
类型一起使用。
bool_prefix
bool_prefix
类型的评分行为类似于most_fields
,但使用 match_bool_prefix
查询 而不是 match
查询。
GET /_search
{"query": {"multi_match" : {"query": "quick brown f","type": "bool_prefix","fields": [ "subject", "message" ]}}
}
支持 match 查询 中所述的参数 analyzer
、boost
、operator
、minimum_should_match
、lenient
、zero_terms_query
及 auto_generate_synonyms_phrase_query
。 用于构建词项(term, "条件"??)查询的词项支持fuzziness
、prefix_length
、max_expansions
、rewrite
及 fuzzy_transpositions
参数,但这些参数对从最终的词项构建的前缀查询没有作用。
该查询类型不支持slop
和 cutoff_frequency
参数。
例如
GET /_search
{"query": {"multi_match" : {"query": "xiaomi nfc phone", "fields": [ "name", "description" ] }}
}`
这个查询会在 "name" 和 "description" 两个字段中查找包含 "xiaomi nfc phone" 的文档。
multi_match
还支持多种类型的匹配模式,如:best_fields
, most_fields
, cross_fields
, phrase
, phrase_prefix
等。这些类型的行为略有不同,可以按照实际需求进行选择。
例如,“best_fields” 类型会从指定的字段中挑选分数最高的匹配结果计算最终得分,而 “most_fields” 类型则会在每个字段中都寻找匹配项并将其分数累加起来。
需要注意的是,当使用 multi_match
查询时,如果字段不同,其权重可能也会不同。你可以通过在字段名后面添加尖括号(^)和权重值来调整特定字段的权重。例如,"fields": [ "name^3", "description" ]
表示在 "name" 字段中的匹配结果权重是"description"字段的三倍。
多字段匹配(multi_match)查询
multi_match
查询建立在 match
查询的基础上,以允许 多字段(multi-field) 查询:
GET /_search
{"query": {"multi_match" : {"query": "this is a test", "fields": [ "subject", "message" ] }}
}
- 要查询的字符串。
- 要查询的字段。
fields
和 字段增强(per-field boosting)
可以使用通配符指定字段名称,比如:
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","fields": [ "title", "*_name" ] }}
}
- 查询
title
、first_name
和last_name
字段。
单个字段可以用脱字符号(^
)来增强:
GET /_search
{"query": {"multi_match" : {"query" : "this is a test","fields" : [ "subject^3", "message" ] }}
}
- 字段
subject
的重要性是message
的3
倍。
如果未指定fields
,则multi_match
查询默认使用index.query.default_field
索引设置,该设置又默认为*
。*
提取映射中符合条件查询的所有字段,并过滤元数据字段。 然后将所有提取的字段组合起来构建一个查询。
一次可以查询的字段数量是有限制的。 它由
indices.query.bool.max_clause_count
搜索设置] 定义的,默认为 1024。
multi_match
查询的类型:
multi_match
查询在内部执行的方式取决于参数 type
,该参数可设置为:
参数 | 含义 |
---|---|
best_fields |
(默认) 查找与任何字段匹配的文档,但使用最佳字段的 _score 。参见 best_fields 。 |
most_fields |
查找与任何字段匹配的文档,并合并每个字段的 _score 。参见 most_fields 。 |
cross_fields |
用相同的 analyzer 处理字段,就好像它们是一个大字段。 在 任何 字段中查找每个单词。 参见 cross_fields 。 |
phrase |
对每个字段运行 match_phrase 查询,并使用最佳字段(best field)的 _score 。 参见 phrase 和 phrase_prefix 。 |
phrase_prefix |
对每个字段运行 match_phrase_prefix 查询,并使用最佳字段(best field)的 _score 。 参见 phrase和 phrase_prefix`。 |
bool_prefix |
在每个字段上创建 match_bool_prefix 查询,并组合每个字段的 _score 。 参见 bool_prefix 。 |
best_fields
best_fields
类型在搜索同一字段中最容易找到的多个单词时最有用。 例如,一个字段里的“brown fox”比一个字段里的“brown”和另一个字段里的“fox”更有意义。
best_fields
类型为每个字段生成一个match
查询,并将它们包裹在一个 dis_max
查询中,以找到单个最佳匹配字段。 比如下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "brown fox","type": "best_fields","fields": [ "subject", "message" ],"tie_breaker": 0.3}}
}
在执行时会被转换为:
GET /_search
{"query": {"dis_max": {"queries": [{ "match": { "subject": "brown fox" }},{ "match": { "message": "brown fox" }}],"tie_breaker": 0.3}}
}
通常,best_fields
类型使用单个最佳匹配字段的分数,但如果指定了tie_breaker
,则它会按如下方式计算分数:
- 最佳匹配字段的分数
- 给所有其他匹配的字段加上
tie_breaker * _score
此外,接受analyzer
、boost
、operator
、minimum_should_match
、fuzziness
、lenient
、prefix_length
、max_expansions
、rewrite
、zero_terms_query
、cutoff_frequency
、auto_generate_synonyms_phrase_query
及fuzzy_transpositions
,如 match 查询 中所述。
operator
和minimum_should_match`` ``best_fields
和most_fields
类型是以字段为中心(field-centric)的,它们为每个字段生成一个match
查询。 这意味着operator
和minimum_should_match
参数分别应用于每个字段,这可能不是你想要的。
以下面这个查询为例:
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","type": "best_fields","fields": [ "first_name", "last_name" ],"operator": "and" }}
}
- 所有词项必须都出现。
该查询按如下方式执行:(+first_name:will +first_name:smith)
| (+last_name:will +last_name:smith)
换句话说,所有词项必须出现在一个字段中,文档才能匹配。
更好的解决方案请参考cross_fields
。
most_fields
当查询包含以不同方式分析的相同文本的多个字段时,most_fields
类型最有用。 例如,主字段可能包含同义词(synonyms)、词干(stemming)和不带发音符号(diacritics)的词项。 第二个字段可能包含原始的(original)词项(term),第三个字段可能包含 shingles(不知道该怎么翻译)。 通过组合所有三个字段的分数,我们可以将尽可能多的文档与主字段匹配,但使用第二个和第三个字段将最相似的结果推到列表的顶部。
下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "quick brown fox","type": "most_fields","fields": [ "title", "title.original", "title.shingles" ]}}
}
在执行时会被转换为:
GET /_search
{"query": {"bool": {"should": [{ "match": { "title": "quick brown fox" }},{ "match": { "title.original": "quick brown fox" }},{ "match": { "title.shingles": "quick brown fox" }}]}}
}
每个 match
子句的得分相加,然后除以 match
子句的数量。
此外,接受analyzer
、boost
、operator
、minimum_should_match
、fuzziness
、lenient
、prefix_length
、max_expansions
、rewrite
、zero_terms_query
及 cutoff_frequency
,如 match 查询 中所述,但是 请参见 operator 和 minimum_should_match。
phrase
和 phrase_prefix
phrase
和 phrase_prefix
类型的行为类似于best_fields
,但是它们使用 match_phrase
或 match_phrase_prefix
查询而不是 match
查询。
下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "quick brown f","type": "phrase_prefix","fields": [ "subject", "message" ]}}
}
在执行时会被转换为:
GET /_search
{"query": {"dis_max": {"queries": [{ "match_phrase_prefix": { "subject": "quick brown f" }},{ "match_phrase_prefix": { "message": "quick brown f" }}]}}
}
此外,还接受 match 中所述的 analyzer
、boost
、lenient
及 zero_terms_query
,以及 match phrase 中介绍的 slop
。 phrase_prefix
类型还接受 max_expansions
。
phrase
,phrase_prefix
和fuzziness
参数fuzziness
不能与phrase
和phrase_prefix
一起使用。
cross_fields
cross_fields
类型对于多个字段should(应该) 匹配的结构化文档特别有用。 例如,当在 first_name
和 last_name
字段查询“Will Smith”时,最佳匹配可能是一个字段中有“Will ”,另一个字段中有“Smith”。
这听起来像是
most_fields
的工作,但是那个方法有两个问题。
第一个问题是operator
和minimum_should_match
是按字段应用的,而不是按词项应用的(见上面的解释)。
第二个问题与相关性有关:first_name
和last_name
字段中不同的词频可能会产生意外的结果。
例如,假设我们有两个人:“Will Smith“ 和 “Smith Jones“。 “Smith“ 作为 姓(last name) 是很常见的(因此不太重要),但是“Smith“作为 名(first name) 是很少见的(因此非常重要)。
如果我们搜索“Will Smith“,文档“Smith Jones”可能会出现在更匹配的“Will Smith”之上,因为first_name:smith
的分数已经超过了first_name:will
加上last_name:smith
的组合分数。
处理这些类型的查询的一种方法是简单地将 first_name
和 last_name
字段索引到单个full_name
字段中。当然,这只能在索引时完成。
cross_field
类型试图通过采用*以词项为中心(term-centric)*的方法在查询时解决这些问题。 它首先将查询字符串分析成单个词项,然后在任何字段中查找每个词项,就好像它们是一个大字段一样。
像下面这样的一个查询
GET /_search
{"query": {"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "first_name", "last_name" ],"operator": "and"}}
}
会被执行为:
+(first_name:will last_name:will)
+(first_name:smith last_name:smith)
换句话说,所有词项 必须出现在至少一个字段中,文档才能匹配。 (将这与 用于 best_fields
和 most_fields
的逻辑 进行比较。)
这解决了两个问题中的一个。 不同词频的问题通过混合(blending)所有字段的词频以消除差异来解决。
实际上,first_name:smith
将被视为与last_name:smith
+ 1 具有相同的频率。 这将使 first_name
和 last_name
的匹配项具有可比较的分数,last_name
有一点优势,因为它是最有可能包含smith
的字段。
请注意,cross_fields
通常只对 boost
都为 1
的短字符串字段有用。 否则 boost、词频和长度归一化会以这样的一种方式影响分数,以至于词项统计数据的混合不再有意义。
如果你通过 Validate API 运行上述查询,它将返回如下解释:
+blended("will", fields: [first_name, last_name])
+blended("smith", fields: [first_name, last_name])
此外,还接受 analyzer
、boost
、operator
、minimum_should_match
、lenient
、zero_terms_query
及 cutoff_frequency
,如 match 查询 中所述。
cross_field
和分析(analysis)
cross_field
类型只能在具有相同分析器的字段上以词项为中心(term-centric)的模式下工作。 如上例所示,具有相同分析器的字段被分组在一起。 如果有多个组,它们将与一个 bool
查询组合在一起。
例如,如果字段 first
和 last
具有相同的分析器,加上 first.edge
和 last.edge
都使用 edge_ngram
分析器,则下面这个查询
GET /_search
{"query": {"multi_match" : {"query": "Jon","type": "cross_fields","fields": ["first", "first.edge","last", "last.edge"]}}
}
将被执行为:
blended("jon", fields: [first, last])
| (
blended("j", fields: [first.edge, last.edge])
blended("jo", fields: [first.edge, last.edge])
blended("jon", fields: [first.edge, last.edge])
)
换句话说,first
和 last
将被分组在一起并被视为单个字段,first.edge
and last.edge
将被分组在一起并被视为单个字段。
拥有多个组是可以的,但是当与 operator
或 minimum_should_match
结合使用时,它可能会遇到与most_fields
或 best_fields
相同的问题。
可以很容易地将该查询重写为两个单独的 cross_fields
查询与一个 bool
查询的组合,并将 minimum_should_match
参数应用于其中一个查询:
GET /_search
{"query": {"bool": {"should": [{"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "first", "last" ],"minimum_should_match": "50%" }},{"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "*.edge" ]}}]}}
}
will
或smith
必须出现在first
或last
字段中
通过在查询中指定analyzer
参数,可以强制将所有字段归入同一组。
GET /_search
{"query": {"multi_match" : {"query": "Jon","type": "cross_fields","analyzer": "standard", "fields": [ "first", "last", "*.edge" ]}}
}
- 对所有字段使用
standard
分析器。
它将被执行为:
blended("will", fields: [first, first.edge, last.edge, last])
blended("smith", fields: [first, first.edge, last.edge, last])
tie_breaker
默认情况下,每个按词项 blended
(混合的) 查询将使用组中任何字段返回的最佳分数,然后将这些分数相加得到最终分数。 参数 tie_breaker
可以更改按词项 blended
(混合的) 查询的默认行为。 它接受:
参数 | 含义 |
---|---|
0.0 |
取单个最佳分数(默认)。(比如从first_name:will 和last_name:will 中取最佳分数) |
1.0 |
将分数相加。(比如把first_name:will 和last_name:will 的分数相加) |
0.0 < n < 1.0 |
将单个最佳分数加上 tie_breaker 乘以其他匹配字段中的每个分数。 |
cross_fields
和fuzziness
参数fuzziness
不能与cross_fields
类型一起使用。
bool_prefix
bool_prefix
类型的评分行为类似于most_fields
,但使用 match_bool_prefix
查询 而不是 match
查询。
GET /_search
{"query": {"multi_match" : {"query": "quick brown f","type": "bool_prefix","fields": [ "subject", "message" ]}}
}
支持 match 查询 中所述的参数 analyzer
、boost
、operator
、minimum_should_match
、lenient
、zero_terms_query
及 auto_generate_synonyms_phrase_query
。 用于构建词项(term, "条件"??)查询的词项支持fuzziness
、prefix_length
、max_expansions
、rewrite
及 fuzzy_transpositions
参数,但这些参数对从最终的词项构建的前缀查询没有作用。
该查询类型不支持slop
和 cutoff_frequency
参数。
query_string(查询字符串查询)
Query String Query 是 ElasticSearch 中的一种查询方式,它允许你使用特定的搜索语法来进行复杂的、灵活的查询。
使用具有严格语法的解析器,根据提供的查询字符串返回文档。
该查询使用一种语法,根据运算符(如AND
或 NOT
)来解析和拆分所给的查询字符串。 在返回匹配的文档之前,查询会单独分析每个拆分出的文本。
可以使用 query_string
查询创建包含通配符的复杂搜索、跨多个字段的搜索等等。 虽然该查询是通用的,但它却很严格,如果查询字符串包含任何无效语法,就会返回错误。
因为它会因为任何无效的语法而返回错误,所以我们不建议对搜索框使用
query_string
查询。
如果不需要支持查询语法,可以考虑使用match
查询。 如果需要查询语法的特性,请使用simple_query_string
查询,它没有那么严格。
Query String Query 是基于 Lucene Query Parser 解析器的,因此支持丰富的搜索语法,包括但不限于:
- 基本文本查询: "quick brown fox"
- 逻辑操作符 (AND, OR, NOT): "quick AND brown"
- 范围查询: "age:[18 TO 30]"
- 通配符查询: "qu?ck br*wn"
- 分组: "(quick OR brown) AND fox"
- 字段指定查询: "title:quick"
下面是几个例子:
查询所有
GET /product/_search
分页
GET /product/_search?from=0&size=2&sort=price:asc
精准匹配 exact value
GET /product/_search?q=date:2021-06-01
_all 搜索 相当于在所有有索引的字段中检索
all 搜索与精准匹配就是带不带字段参数的区别,如果把 index 索引禁用,则 all 搜索不会去该字段上查询。
GET /product/_search?q=2021-06-01
请求示例
当执行下面的搜索时,query_string
查询将 (new york city) OR (big apple)
拆分成两个部分:new york city
和 big apple
。 然后,在返回匹配的文档之前,content
字段的分析器单独将每个部分转换成词元(token)。 因为查询语法不使用空格作为运算符,所以 new york city
按原样传递给分析器。
GET /_search
{"query": {"query_string" : {"query" : "(new york city) OR (big apple)","default_field" : "content"}}
}
query_string
的顶级参数
query
(必需的, string) 希望解析并用于搜索的查询字符串。参考查询字符串语法。default_field
(可选, string) 如果查询字符串中没有指定字段,你希望搜索的默认字段。默认为index.query.default_field
索引设置,其默认值为*
。*
值提取符合条件查询的所有字段,并过滤元数据字段。 如果没有指定prefix
,则将所有提取出来的字段组合起来构建一个查询。在所有符合要求的字段中搜索并不会包括 嵌套文档,请使用nested
查询 来搜索这些文档。对于包含大量字段的映射,在所有符合条件的字段中进行搜索的成本可能会非常高。一次可以查询的字段数量是有限制的。 它由indices.query.bool.max_clause_count
搜索设置定义,默认为 1024。allow_leading_wildcard
(可选, boolean) 如果为true
,通配符*
和?
允许作为查询字符串的第一个字符。默认为true
。analyze_wildcard
(可选, boolean) 如果为true
,查询将尝试分析查询字符串中的通配符。默认为false
。analyzer
(可选, string) 用于将查询字符串中的文本转换为词元(token)的分析器。 默认为字段default_field
所映射的 索引时使用的分析器。 如果没有映射分析器,则使用索引的默认分析器。auto_generate_synonyms_phrase_query
(可选, boolean) 如果为true
,将自动为多词项同义词创建 匹配短语(match phrase)查询。 默认为true
。 有关示例请参考 同义词和query_string
查询。boost
(可选, float) 用于降低或增加查询的相关性评分的浮点数。默认为1.0
。boost 值是相对于默认值1.0
的。 当它在0
和1.0
之间时会降低相关性评分,而大于1.0
时会增加相关性评分。default_operator
(可选, string) 未指定运算符时,用于解释查询字符串中的文本的默认的布尔逻辑。有效值有:OR
(默认)比如,查询字符串capital of Hungary
被解释为capital OR of OR Hungary
。AND
比如,查询字符串capital of Hungary
被解释为capital AND of AND Hungary
。enable_position_increments
(可选, boolean) 如果为true
,则在由query_string
搜索构建的查询中启用位置增量。默认为true
。fields
(可选, array of strings) 你想搜索的字段的数组。可以使用此参数跨多个字段进行搜索。参考搜索多个字段。fuzziness
(可选, string) 匹配时的最大编辑距离。有效值及更多信息请参考模糊性。fuzzy_max_expansions
(可选, integer) 模糊匹配查询能扩展到的最大词项数。默认为50
。fuzzy_prefix_length
(可选, integer) 模糊匹配的起始字符保持不变的字符数量。默认为0
。fuzzy_transpositions
(可选, boolean) 如果为true
,模糊匹配的编辑可以包含两个相邻字符的交换(ab → ba)。默认为true
。lenient
(可选, boolean) 如果为true
,则忽略基于格式的错误,例如为 numeric 字段提供 text 值。 默认为false
。max_determinized_states
(可选, integer) 查询所需的自动机状态的最大值。默认为10000
。ElasticSearch 内部使用Apache Lucene解析正则表达式。 Lucene 将每个正则表达式转换成一个包含许多确定状态的有限自动机。可以使用此参数来防止该转换无意中消耗太多资源。你可能需要提高这个限制来运行复杂的正则表达式。minimum_should_match
(可选, string) 要返回的文档必须匹配的最小子句数。 有效值及更多信息请参考minimum_should_match
参数。 查看minimum_should_match
如何工作的示例。quote_analyzer
(可选, string) 用于将查询字符串中的引用文本转换为词元(token)的分析器。 默认为字段default_field
映射的search_quote_analyzer
。对于引用的文本,此参数会覆盖analyzer
参数中指定的分析器。phrase_slop
(可选, integer) 短语的匹配词元之间允许的最大位置数。默认为0
。 如果为0
,则要求精确的短语匹配。 颠倒顺序的词项的 slop 的值为2
。quote_field_suffix
(可选, string) 查询字符串中附加到引用文本的后缀。可以使用此后缀来使用不同的分析方法进行精确匹配。参考 将精确搜索与词干混合。rewrite
(可选, string) 用于重写查询的方法。有效值及更多信息请参考rewrite
参数。time_zone
(可选, string) 协调世界时(UTC)时差或 IANA时区,用于将查询字符串中的date
值转换为 UTC。有效值包括 ISO 8601 UTC 时差,如+01:00
或-08:00
,以及 IANA 时区识别名称,如America/Los_Angeles
。time_zone
参数不影响now
的 日期计算]值。now
始终是 UTC 中的当前系统时间。 但是,time_zone
参数会对使用now
和 日期计算舍入计算的日期进行转换。 例如,time_zone
参数会将now/d
的值进行转换。
注意事项
查询字符串语法
查询字符串“迷你语言”由 search
API 中的 查询字符串和 q
查询字符串参数使用。
查询字符串被解析为一系列 词项(term) 和 运算符(operator) 。 词项(term)可以是一个单词(如quick
或 brown
),也可以是一个用双引号括起来的短语(如"quick brown"
) - 它以相同的顺序搜索短语中的所有单词。
运算符允许你自定义搜索—可用选项如下所述。
字段名称(field names)
可以在查询语法中指定要搜索的字段,下面是几个例子:
-
status
字段中包含单词active
:status:active
-
title
字段中包含单词quick
或brown
:title:(quick OR brown)
-
author
字段中包含精确匹配的短语"john smith"
:author:"John Smith"
-
first name
字段包含Alice
(注意,我们需要用反斜杠转义字段名称中的空格):first\ name:Alice
-
book.title
、book.content
或book.date
任意一个字段中包含单词quick
或brown
(注意,我们需要用反斜杠转义字段名称中的*
):book.*:(quick OR brown)
-
字段
title
有任何非null的值(只要存在这个字段,即使其值是空字符串):_exists_:title
通配符
通配符搜索可以在单个词项上运行,使用 ?
替换单个字符,使用 *
替换零个或多个字符:
qu?ck bro*
请注意,通配符查询会占用大量内存,并且性能非常差——只要想想需要查询多少个词项才能匹配查询字符串 "a* b* c*"
。
为了提高效率,纯通配符
\*
被重写为exists
查询。 因此,通配符"field:*"
将匹配具有空值的文档,如下所示:
{"field": ""
}
如果字段缺失或设置了显式的 null 值,则 不 匹配,如下所示:
{"field": null
}
允许在单词的开头使用通配符(例如
"*ing"
)的资源消耗特别大,因为需要检查索引中的所有词项,以防它们匹配。 通过将allow_leading_wildcard
设置为false
,可以禁用前置通配符。
只有部分分析链应用在字符级别的操作上。 例如,如果分析器既执行转小写又执行词干分析(提取),那么只会应用转小写操作:对一个缺少某些字母的单词执行词干分析是错误的。
通过将 analyze_wildcard
设置为true,将分析以 *
结尾的查询,通过确保前 N-1 个词元(token)的精确匹配和最后一个词元的前缀匹配,从不同的词元中构建 bool 查询。
正则表达式
通过将正则表达式模式用斜杠("/"
)包裹,可以将它们嵌入到查询字符串中:
name:/joh?n(ath[oa]n)/
正则表达式语法 中解释了支持的正则表达式语法。
allow_leading_wildcard
参数对正则表达式没有任何控制。 下面这个查询字符串将强制 ElasticSearch 访问索引中的每个词项:
/.*n/
慎用!
模糊性(Fuzziness)
我们可以使用“模糊”运算符搜索与我们的搜索词项相似但又不完全相似的词项:
quikc~ brwn~ foks~
它使用 达梅劳-莱温斯坦距离 来查找最多有两个变化的所有词项,其变化包括单个字符的插入、删除或替换,或者两个相邻字符的位置调换。
默认的编辑距离是2
,但是编辑距离1
应该足以捕捉 80% 的人类拼写错误。 它可以指定为:
quikc~1
避免混合使用模糊性和通配符
不 支持混合使用 模糊 和 通配符 运算符。 混合使用时,其中一个运算符不会被应用。 例如,可以搜索
app~1
(模糊)或app*
(通配符),但搜索app*~1
时不会应用模糊运算符(~1
)。
邻近搜索 (proximity searches)
虽然短语查询(例如"john smith"
)希望所有词项的顺序完全相同,但 邻近查询(proximity query) 允许指定的词语相距更远或顺序不同。 与 模糊查询(fuzzy query) 可以指定单词中字符的最大编辑距离相同,邻近搜索允许我们指定短语中单词的最大编辑距离:
"fox quick"~5
字段中的文本越接近查询字符串中指定的原始顺序,该文档就被认为越相关。 与上面的示例查询相比,短语 "quick fox"
被认为比 "quick brown fox"
更相关。
范围 (ranges)
可以为 date、numeric 或 string 字段指定范围。 包含范围用方括号[min TO max]
表示,不包含范围用花括号{min TO max}
表示。
-
2012年内的所有天数:
date:[2012-01-01 TO 2012-12-31]
-
数字 1 到 5:
count:[1 TO 5]
-
介于
alpha
和omega
之间的标签,但不包含alpha
和omega
:tag:
-
10以上的数字:
count:[10 TO *]
-
2012年之前的日期:
date:
大括号和方括号可以组合使用:
- 从 1 到 5 的数字,但不包括 5:
count:[1 TO 5}
一侧无界的范围可以使用以下语法:
age:>10
age:>=10
age:<10
age:<=10
要使用简化的语法组合上限和下限,需要用AND
运算符连接两个子句:age:(>=10 AND <20)
age:(+>=10 +<20)
查询字符串中范围的解析可能很复杂并且容易出错。 使用显式的 range
查询 要可靠得多。
增强 (boosting)
使用 增强(boost) 运算符 ^
使一个词项比另一个更相关。 例如,如果我们想找到所有关于 fox
的文档,但是我们对 quick fox
特别感兴趣:
quick^2 fox
默认 boost
的值为 1,但可以是任何正浮点数。 boost
的值在 0 到 1 之间时会降低相关性。
boost
也可用于短语或分组:
"john smith"^2 (foo bar)^4
布尔运算符 (boolean operators)
默认情况下,所有词项都是可选的,只要有一个词项匹配即可。 搜索 foo bar baz
将找到包含 foo
、bar
、baz
中的一个或多个的任何文档。 我们在上面已经讨论了 default_operator
,它允许你强制所有的词项都是必需的,但是也有一些布尔运算符可以在查询字符串本身中使用,以提供更多的控制。
首选运算符是 +
(该词项必须存在) 和 -
(该词项 必须不 存在)。所有其他词项都是可选的。 例如,下面这个查询:
quick brown +fox -news
说明:
fox
必须存在news
必须不存在quick
和brown
是可选的,但如果他们存在则会增加相关性
我们所熟悉的布尔运算符AND
、OR
和NOT
(也写成&&
、||
和!
)也是受支持的,但要注意它们不遵守通常的优先规则,所以当多个运算符一起使用时,应该使用括号。 例如,前面的查询(即: quick brown +fox -news)可以重写为:((quick AND fox) OR (brown AND fox) OR fox) AND NOT news
这种形式现在正确地复制了原查询的逻辑,但是相关性评分与原查询几乎没有相似之处。
相比之下,使用match
查询 重写的相同查询会像这样:
{"bool": {"must": { "match": "fox" },"should": { "match": "quick brown" },"must_not": { "match": "news" }}
}
分组 (grouping)
多个词项或子句可以用括号组合在一起,形成子查询:
(quick OR brown) AND fox
组可用于针对特定字段,或增强子查询的结果:
status:(active OR pending) title:(full text search)^2
保留字符
如果你需要在查询本身中使用任何起运算符作用的字符(而不是运算符),那么你应该在前面加一个反斜杠对它们进行转义。 例如,要搜索 (1+1)=2
,你需要将查询写成 \(1\+1\)\=2
。 当请求体使用 JSON 时,前面需要两个反斜杠(\\
);反斜杠是 JSON 字符串中保留的转义字符。
GET /twitter/_search
{"query" : {"query_string" : {"query" : "kimchy\\!","fields" : ["user"]}}
}
保留字符有:+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
未能正确转义这些特殊字符可能会导致语法错误,从而使查询无法运行。
<
和>
根本不能进行转义。 防止他们试图创建范围查询的唯一方法是将他们从查询字符串中完全删除。
空格和空查询 (whitespaces and empty queries)
空格(whitespace)不被当做运算符。
如果查询字符串为空或者只包含空格,查询将产生一个空的结果集。
避免对嵌套文档使用 query_string
查询
query_string
搜索不会返回 嵌套的(nested) 文档。 要搜索嵌套文档,请使用 nested
查询]。
搜索多个字段
可以使用 fields
参数同时对多个字段执行 query_string
搜索。
对多个字段运行 query_string
查询的想法是将每个查询词项扩展为一个 OR 子句,如下所示:
field1:query_term OR field2:query_term | ...
例如,这个查询
GET /_search
{"query": {"query_string" : {"fields" : ["content", "name"],"query" : "this AND that"}}
}
与下面这个查询匹配相同的词:
GET /_search
{"query": {"query_string": {"query": "(content:this OR name:this) AND (content:that OR name:that)"}}
}
由于几个查询是从单个搜索词项中生成的,所以使用带有 tie_breaker
的 dis_max
查询自动完成对它们的组合。 例如(使用符号 ^5
将 name
增加 5):
GET /_search
{"query": {"query_string" : {"fields" : ["content", "name^5"],"query" : "this AND that OR thus","tie_breaker" : 0}}
}
简单通配符也可以用于“在”文档指定的内部元素中搜索。 例如,如果有一个包含多个字段的 city
对象(或包含几个字段的内部对象),则可以自动搜索所有"city"字段:
GET /_search
{"query": {"query_string" : {"fields" : ["city.*"],"query" : "this AND that OR thus"}}
}
另一个选项是在查询字符串本身中提供通配符字段搜索(正确转义 *
标志),例如:city.\*:something
:
GET /_search
{"query": {"query_string" : {"query" : "city.\\*:(this AND that OR thus)"}}
}
由于
\
(反斜杠)是 json 字符串中的一个特殊字符,因此需要转义,因此在上面的query_string
中有两个反斜杠。
fields 参数还可以包括基于模式的字段名,允许自动展开到相关字段(包括动态引入的字段)。例如:
GET /_search
{"query": {"query_string" : {"fields" : ["content", "name.*^5"],"query" : "this AND that OR thus"}}
}
多字段搜索的附加参数
当对多个字段运行 query_string
查询时,支持下列附加参数。
type
(可选, string) 确定查询如何对文档进行匹配和评分。有效值有:best_fields
(默认) 查找与任何字段匹配的文档,并使用任何匹配字段中的最高的_score
。 参见best_fields
。bool_prefix
在每个字段上创建match_bool_prefix
查询,并组合每个字段的_score
。 参见bool_prefix
。cross_fields
用相同的analyzer
处理字段,就好像它们是一个大字段。 在 任何 字段中查找每个单词。 参见cross_fields
]。most_fields
查找与任何字段匹配的文档,并合并每个字段的_score
。参见most_fields
。phrase
Seephrase
andphrase_prefix
. 对每个字段运行match_phrase
查询,并使用最佳字段(best field)的_score
。 参见phrase
和phrase_prefix
。phrase_prefix
对每个字段运行match_phrase_prefix
查询,并使用最佳字段(best field)的_score
。 参见phrase
和phrase_prefix
。注意:根据type
的值,multi_match
可能有额外的顶级参数。
同义词与query_string
查询
query_string
查询支持 synonym_graph 词元过滤器(token filter)的多词项同义词扩展。 当使用该过滤器时,解析器将为每个多词项同义词创建一个短语查询。 例如,同义词 ny, new york
将产生:
(ny OR ("new york"))
还可以用"逻辑与"匹配多个词项同义词代替:
GET /_search
{"query": {"query_string" : {"default_field": "title","query" : "ny city","auto_generate_synonyms_phrase_query" : false}}
}
上面的示例创建了一个 bool 查询:
(ny OR (new AND york)) city
它将文档与词项 ny
或 逻辑与new AND york
相匹配。 默认情况下,参数 auto_generate_synonyms_phrase_query
设置为 true
。
minimum_should_match
是如何工作的
query_string
根据每个运算符拆分查询,从而为整个输入创建布尔查询。 可以使用minimum_should_match
来控制结果查询中应该匹配的“should”子句的数量。
GET /_search
{"query": {"query_string": {"fields": ["title"],"query": "this that thus","minimum_should_match": 2}}
}
上面的例子创建了一个 bool 查询:
(title:this title:that title:thus)~2
它将返回单个字段title
与至少this
、that
或 thus
中的2个词项匹配的文档。
minimum_should_match
如何处理多个字段的匹配
GET /_search
{"query": {"query_string": {"fields": ["title","content"],"query": "this that thus","minimum_should_match": 2}}
}
上面的例子创建了一个bool查询:
((content:this content:that content:thus) | (title:this title:that title:thus))
它使用"逻辑或"最大限度的通过title
和content
字段去匹配文档。 这里无法应用minimum_should_match
参数。
GET /_search
{"query": {"query_string": {"fields": ["title","content"],"query": "this OR that OR thus","minimum_should_match": 2}}
}
添加显式运算符(OR
)强制每个词项被视为一个单独的子句。
上面的例子创建了一个 bool 查询:
((content:this | title:this) (content:that | title:that) (content:thus | title:thus))~2
这使文档至少与三个“should”子句中的两个匹配,每个子句都是由每个词项的字段上的最大"逻辑或"构成的。
minimum_should_match
如何处理跨字段搜索
字段type
的值为cross_fields
时,对在分析输入时使用了相同分析器的字段进行分组。
GET /_search
{"query": {"query_string": {"fields": ["title","content"],"query": "this OR that OR thus","type": "cross_fields","minimum_should_match": 2}}
}
上面的例子创建了一个 bool 查询:
(blended(terms:[field2:this, field1:this]) blended(terms:[field2:that, field1:that]) blended(terms:[field2:thus, field1:thus]))~2
这将匹配与三个词项混合(blended)查询中的至少两个匹配的文档。
注意
允许执行昂贵的查询
查询字符串查询可以在内部转换为prefix查询
,这意味着如果如这里所解释的那样禁用前缀查询,则查询字符串查询将不会被执行并抛出异常。
简单查询字符串(simple_query_string)查询
使用一个语法有限但可以容错的解析器,根据提供的查询字符串返回文档。
这个查询使用一个简单的语法来解析给定的查询字符串,并根据特殊的操作符将其拆分成多个词项。 然后,在返回匹配的文档之前,查询会单独分析每个词项。
虽然它的语法比query_string
查询更有限,但simple_query_string
查询不会因为无效语法而返回错误。 相反,它会忽略查询字符串的任何无效部分。
请求示例
GET /_search
{"query": {"simple_query_string" : {"query": "\"fried eggs\" +(eggplant | potato) -frittata","fields": ["title^5", "body"],"default_operator": "and"}}
}
simple_query_string
的顶级参数
-
query
(必需的, string) search. 要解析并用于搜索的查询字符串。参考 简单查询字符串语法. -
fields
(可选, array of strings) 要搜索的字段的数组。该字段接受通配符表达式。还可以使用脱字符号(^
)来提高匹配时的特定字段的相关性分数。 有关示例请参考fields
参数中的通配符和按字段增强。默认为index.query.default_field
索引设置,其默认值为*
。*
值提取符合条件查询的所有字段,并过滤元数据字段。 如果没有指定prefix
,那么将所有提取的字段组合起来构建一个查询。一次可以查询的字段数量是有限制的。
它由indices.query.bool.max_clause_count
搜索设置定义,默认为1024
。 -
default_operator
(可选, string) 未指定运算符时,用于解释查询字符串中的文本的默认的布尔逻辑。有效值有:OR
(默认) 比如,查询字符串capital of Hungary
被解释为capital OR of OR Hungary
。AND
比如,查询字符串capital of Hungary
被解释为capital AND of AND Hungary
。 -
all_fields
[6.0.0] 在6.0.0中废弃。使用设置fields
为*
来代替(可选, boolean) 如果为true
,则搜索索引字段映射中的所有可搜索字段。 -
analyze_wildcard
(可选, boolean) 如果为true
,查询将尝试分析查询字符串中的通配符。默认为false
。 -
analyzer
(可选, string) 用于将查询字符串中的文本转换为词元(token)的分析器。 默认为字段default_field
所映射的 索引时使用的分析器。 如果没有映射分析器,则使用索引的默认分析器。 -
auto_generate_synonyms_phrase_query
(可选, boolean) 如果为true
,将自动为多词项同义词创建匹配短语(match phrase)查询。 默认为true
。 有关示例请参考同义词。 -
flags
(可选, string)简单查询字符串语法启用的运算符的列表。 默认为ALL
(所有运算符)。 有效值请参考有限运算符。 -
fuzzy_max_expansions
(可选, integer) 模糊匹配查询能扩展到的最大词项数。默认为50
。 -
fuzzy_prefix_length
(可选, integer) 模糊匹配的起始字符保持不变的字符数量。默认为0
。 -
fuzzy_transpositions
(可选, boolean) 如果为true
,模糊匹配的编辑可以包含两个相邻字符的交换(ab → ba)。默认为true
。 -
lenient
(可选, boolean) 如果为true
,则忽略基于格式的错误,例如为 numeric 字段提供 text 值。 默认为false
。 -
minimum_should_match
(可选, string) 要返回的文档必须匹配的最小子句数。 有效值及更多信息请参考minimum_should_match
参数。 -
quote_field_suffix
(可选, string) 查询字符串中附加到引用文本的后缀。可以使用此后缀来使用不同的分析方法进行精确匹配。参考将精确搜索与词干混合。
注意
简单查询字符串语法
simple_query_string
查询支持以下几个运算符:
+
表示 AND 操作|
表示 OR 操作-
取消单个词元"
包裹一些词元以表示一个要搜索的短语*
在词项的末尾表示前缀查询(
和)
表示优先~N
在一个词的后面时表示编辑距离(模糊性)~N
在一个短语后时表示溢出(slop)量
要按字面意思使用其中一个字符,请在前面加一个反斜杠(\
)进行转义。
根据default_operator
值的不同,这些运算符的行为可能会有所不同。例如:
GET /_search
{"query": {"simple_query_string" : {"fields" : ["content"],"query" : "foo bar -baz"}}
}
该搜索请求旨在仅返回包含foo
或bar
但不包含baz
的文档。 然而,由于default_operator
的值为OR
,该搜索实际上返回包含foo
或bar
的文档以及不包含baz
的任何文档。 要按预期返回文档,请将查询字符串改为 foo bar +-baz
。
限制查询中可以使用的运算符
可以使用flags
参数来限制简单查询字符串语法支持的运算符。
若要显式地仅启用特定的操作符,请使用|
分隔符。 例如,flags
值为OR|AND|PREFIX
时会禁用除OR
、AND
和 PREFIX
之外的所有运算符。
GET /_search
{"query": {"simple_query_string" : {"query" : "foo | bar + baz*","flags" : "OR|AND|PREFIX"}}
}
有效值
flags 的有效值有:
ALL
(默认)
启用所有可选的运算符。AND
启用+
(AND,和/与) 运算符。ESCAPE
启用\
作为转义字符。FUZZY
启用单词后的~N
运算符,其中N
是表示匹配时允许的编辑距离的整数。参考模糊性。NEAR
启用短语后的~N
运算符,其中N
是匹配词元之间允许的最大位置数。与SLOP
同义。NONE
禁用所有运算符。NOT
启用-
(NOT,非) 运算符。OR
启用\|
(OR,或)运算符。PHRASE
启用用于搜索短语的"
引号运算符。PRECEDENCE
允许(
和)
运算符控制运算符优先级。PREFIX
启用*
前缀运算符。SLOP
启用短语后的~N
运算符,其中N
是匹配词元之间允许的最大位置数。与NEAR
同义。WHITESPACE
启用空格作为分割字符。
fields
参数中的通配符和按字段增强
可以用通配符指定字段,例如:
GET /_search
{"query": {"simple_query_string" : {"query": "Will Smith","fields": [ "title", "*_name" ] }}
}
- 查询
title
、first_name
和last_name
字段。
单个字段可以用脱字符号(^
)来增强:
GET /_search
{"query": {"simple_query_string" : {"query" : "this is a test","fields" : [ "subject^3", "message" ] }}
}
- 字段
subject
的重要性是message
的 3 倍。
同义词
simple_query_string
查询通过 synonym_graph 词元过滤器(token filter)支持多词项同义词扩展。 使用这个过滤器时,解析器为每个多词项同义词创建一个短语查询。 例如,下面的同义词 "ny, new york"
将产生产生:
(ny OR ("new york"))
也可以用逻辑与来匹配多词项同义词:
GET /_search
{"query": {"simple_query_string" : {"query" : "ny city","auto_generate_synonyms_phrase_query" : false}}
}
上面的例子创建了一个 bool 查询:
(ny OR (new AND york)) city)
它匹配带有词项 ny
或 逻辑与 new AND york
的文档。 默认情况下,参数 auto_generate_synonyms_phrase_query
设置为 true
。
精准查询 Term query
精确查询用于查找包含指定精确值的文档,而不是执行全文搜索。
term:匹配和搜索词项完全相等的结果
举个例子:
GET /_search
{"query": {"term": {"user": "kimchy"}}
}
这个查询会找到 "user" 字段精确匹配 "kimchy" 的所有文档。
需要注意的是,term
查询对大小写敏感,并且不会进行分词处理。也就是说,如果你在使用 term
查询时输入了一个完整的句子,它将尝试查找与这个完整句子精确匹配的文档,而不是把句子拆分成单词进行匹配。
term 和 match_phrase 的区别
term
查询和 match_phrase
查询是 ElasticSearch 提供的两种查询方式,它们都用于查找文档,但主要的区别在于如何解析查询字符串以及匹配的精确度。
term
查询:这种查询对待查询字符串为一个完整的单位,不进行分词处理,并且大小写敏感。它可以在文本、数值或布尔类型字段上使用,通常用于精确匹配某个字段的确切值。match_phrase
查询:这种查询把查询字符串当作一种短语来匹配。查询字符串会被分词器拆分成单独的词项,然后按照词项在查询字符串中的顺序去匹配文档。只有当文档中的词项顺序与查询字符串中的顺序完全一致时才能匹配成功,match_phrase 查询通常对大小写不敏感,除非你的字段映射或索引设置更改了这个行为。
简单来说,term
查询更多的是做精确的、字面的匹配,而match_phrase
则是做短语匹配,在搜索结果的精确度上,term
查询比match_phrase
更高。
terms:匹配和搜索词项列表中任意项匹配的结果
terms
查询用于匹配指定字段中包含一个或多个值的文档。这是一个精确匹配查询,不会像全文查询那样对查询字符串进行分析。
假设你有一个 "user" 的字段,并且你想找到该字段值为 "John" 或者 "Jane" 的所有文档,你可以使用 terms
查询:
GET /_search
{"query": {"terms" : {"user" : ["John", "Jane"],"boost" : 1.0}}
}
上面的查询将返回所有 "user" 字段等于 "John" 或者 "Jane" 的文档。
其中boost
参数用于增加或减少特定查询的相对权重。它将改变查询结果的相关性分数(_score),以影响最终结果的排名。
例如,在上述 terms
查询中,boost
参数被设置为 1.0。这意味着如果字段 "user" 的值包含 "John" 或 "Jane",那么其相关性分数(_score)就会乘以 1.0。因此,这个设置实际上并没有改变任何东西,因为乘以 1 不会改变原始分数。但是,如果你将 boost
参数设置为大于 1 的数,那么匹配的文档的 _score 将会提高,反之则会降低。
range:范围查找
range 查询允许你查找位于特定范围内的值。这对于日期、数字或其他可排序类型的字段非常有用。
下面的语句会查询出 age 字段大于等于10,小于等于20的文档。
例子1:假设你有一些表示博客文章的文档,每个文档都有一个发表日期,并且你想找出在特定日期范围内发布的所有文章,你可以使用 range
查询来实现这一目标
GET /_search
{"query": {"range" : {"date" : {"gte" : "2020-01-01","lte" : "2020-12-31","format": "yyyy-MM-dd"}}}
}
在上面的查询中,range
查询被用来查找字段 "date" 的值在 "2020-01-01" 和 "2020-12-31"(包含)之间的所有文档。
range
查询支持以下运算符:
gt
:大于 (greater than)gte
:大于等于 (greater than or equal to)lt
:小于 (less than)lte
:小于等于 (less than or equal to)
例子2:下面的语句会查询出 date 字段 1 天前的文档,其中 now 表示当前时间。
GET product/_search
{"query": {"range": {"date": {"gte": "now-1d/d","lt": "now/d"}}}
}
例子3:下面的语句会查询出 date 字段小于当前时间,大于 2021-04-15T08:00:00 的文档。time_zone 表示时区,意思就是原文档中的数据会被 +8 小时再去搜索,例如原文档有条数据是:2021-04-15。则该数据能被查询出来。
GET product/_search
{"query": {"range": {"date": {"time_zone": "+08:00","gte": "2021-04-15T08:00:00","lt": "now"}}}
}
过滤器 Filter
过滤器(Filter)是一种特殊类型的查询,它不关心评分 (_score),只关心是否匹配。基于这个原因,过滤器比标准的全文查询更快并且能被缓存。
一个典型的使用场景是布尔查询 (bool
), 它有两个重要的部分:must
和 filter
。must
部分用于全文搜索,filter
部分用于过滤结果。看一个例子:
GET /_search
{"query": {"bool": {"must": [{ "match": { "title": "quick" }}],"filter": [{ "term": { "published": true }}]}}
}
在这个查询中,bool
查询包含了一个 must
子句和一个 filter
子句。must
子句会执行全文搜索并对结果进行评分。在这个例子中,它会找出所有标题包含"quick"的文章。
filter
子句则会在 must
子句的基础上进一步过滤结果。在这个例子中,它会筛选出那些已经发布的文章。这个过滤操作不会影响到评分,因为它只关心是否匹配。
总的来说,过滤器非常适合用于分类、范围查询或者确认某个字段是否存在等场景。过滤器的效率高并且可以被缓存,所以在大型数据集上性能表现良好。
Filter 缓存机制
在 ElasticSearch 中,过滤查询结果的缓存机制是非常重要的一个性能优化手段。由于过滤器(filter)只关心是否匹配,而不关心评分 (_score),因此它们的结果可以被缓存以提高性能。
每次 filter 查询执行时,ElasticSearch 都会生成一个名为 "bitset" 的数据结构,其中每个文档都对应一个位(0 或 1),表示这个文档是否与 filter 匹配。这个 bitset 就是被存储在缓存中的部分。
如果相同的 filter 查询再次执行,ElasticSearch 可以直接从缓存中获取这个 bitset,而不需要再次遍历所有的文档来找出哪些文档符合这个 filter。这大大提高了查询速度,并减少了 CPU 使用。
这种缓存策略特别适合那些重复查询的场景,例如用户界面的过滤器和类似的功能,因为他们通常会产生很多相同的 filter 查询。
然而,值得注意的是,虽然这种缓存可以显著改善查询性能,但也会占用内存空间。如果你有很多唯一的过滤条件,那么过滤器缓存可能会变得很大,从而导致内存问题。这就需要你对使用的过滤器进行适当的管理和限制。
另外,ElasticSearch 默认情况下会自动选择哪些过滤器进行缓存,考虑到查询频率和成本等因素。你也可以手动配置某个特定的 filter 是否需要进行缓存。
复合查询 (compound queries)
复合查询包裹其他复合或叶子查询,要么组合它们的结果和分数以改变它们的行为,要么从 query 切换到 filter 上下文。
该组中的查询包括:
bool(布尔)
查询
用于组合多个叶子查询子句或复合查询子句的默认查询,如must
、should
、must_not
或filter
子句。must
和should
子句将它们的分数组合在一起,且匹配的子句越多越好;而must_not
和filter
子句在 filter 上下文中执行。boosting
查询
返回与positive (肯定)
查询匹配的文档,但同时也会降低与negative (否定)
查询匹配的文档的分数。constant_score(常量分数)
查询
包裹另一个查询,但只在 filter 上下文中执行查询。 所有匹配的文档都被赋予相同的“常数”_score
。dis_max
查询
接受多个查询并返回与任何查询子句匹配的任何文档的查询。 虽然bool
查询组合了所有匹配查询的分数,但是dis_max
查询使用单个最佳匹配查询子句的分数。function_score
查询
使用函数修改主查询返回的分数,以考虑流行度(popularity)、新近度(recency)、距离(distance)或使用脚本(script)实现的自定义算法等因素。
Bool 查询
组合查询可以组合多个查询条件,bool 查询也是采用 more_matches_is_better 的机制,因此满足 must 和 should 子句的文档将会合并起来计算分值。
boot 和 minumum_should_match 是参数,其他四个都是查询子句。
匹配与其他查询的布尔(bool)组合相匹配的文档的查询。 bool 查询映射到 Lucene 的 BooleanQuery
。 它使用一个或多个布尔子句构建,每个子句都有一个类型的出现。 出现的类型包括:
出现 | 描述 |
---|---|
must |
该子句(查询)必须出现在匹配的文档中,并且将参与计算得分。 |
filter |
过滤器不计算相关度分数。该子句(查询)必须出现在匹配的文档中。 然而,与 must 不同,该查询的分数将被忽略。 filter 子句在 filter 的上下文中执行,这意味着该字句的评分会被忽略,但会考虑对该字句进行缓存。 |
should |
该子句(查询) 应该(should) 出现在匹配的文档中。满足 or 子句(查询)应出现在匹配的文档中。 |
must_not |
必须不满足,不计算相关度分数 ,not子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。该子句(查询)不能出现在匹配的文档中。 该子句在[filter 的上下文中执行,这意味着该字句的评分会被忽略,但会考虑对该字句进行缓存。 因为评分被忽略,所以所有文档都返回 |
使用 minimum_should_match
可以使用 minimum_should_match
参数来指定返回文档 必须(must) 匹配的should
子句的数量或百分比。
如果 bool
查询至少包含一个 should
子句,并且没有 must
或 filter
子句,则默认值为 1
。 否则,默认值为 0
。
关于其他可用的值, 参考 minimum_should_match
参数。
用 bool.filter
评分
filter
元素下指定的查询对评分没有影响,因为返回的分数都是 0
。 分数只受已指定的查询的影响。 例如,以下三个查询都返回 status
字段包含词项 active
的所有文档。
第一个查询为所有文档分配 0
分,因为没有指定计分的查询:
GET _search
{"query": {"bool": {"filter": {"term": {"status": "active"}}}}
}
下面这个 bool
查询有一个 match_all
查询,它给所有文档分配 1.0
分。
GET _search
{"query": {"bool": {"must": {"match_all": {}},"filter": {"term": {"status": "active"}}}}
}
第三个例子, 下面这个 constant_score
查询的行为与上面的第二个示例完全相同。constant_score
查询将分数 1.0
分配给与过滤器匹配的所有文档。
GET _search
{"query": {"constant_score": {"filter": {"term": {"status": "active"}}}}
}
使用命名查询(named queries)查看哪子句匹配
如果需要知道 bool 查询中的哪个子句与查询返回的文档相匹配,可以使用 命名查询(named queries)为每个子句指定一个名称。
例子
例子1:下面的语句表示:包含"xiaomi"或"phone" 并且包含"shouji"的文档例子:
GET product/_search
{"query": {"bool": {"must": [{"match": {"name": "xiaomi phone"}},{"match_phrase": {"desc": "shouji"}}]}}
}
should 与 must 或 filter 一起使用
当 should
子句与 must
或 filter
子句一起使用时,这时候需要注意了!只要满足了 must
或 filter
的条件,should
子句就不再是必须的。换句话说,如果存在一个或者多个 must
或 filter
子句,那么 should
子句的条件会被视为可选。
然而,如果 should
子句与 must_not
子句单独使用(也就是没有 must
或 filter
),则至少需要满足一个 should
子句的条件。
这里有一个例子来说明:
GET /_search
{"query": {"bool": {"must": [{ "term": { "user": "kimchy" }}],"filter": [{ "term": { "tag": "tech" }}],"should": [{ "term": { "tag": "wow" }},{ "term": { "tag": "ElasticSearch" }}]}}
}
在这个查询中,must
和 filter
子句的条件是必须满足的,而 should
子句的条件则是可选的。如果匹配的文档同时满足 should
子句的条件,那么它们的得分将会更高。
那如果我们一起使用的时候想让 should 满足该怎么办?这时候minimum_should_match
参数就派上用场了。
minimum_should_match
minimum_should_match 参数定义了在 should
子句中至少需要满足多少条件。
例如,如果你有5个 should
子句并且设置了 "minimum_should_match": 3
,那么任何匹配至少三个 should
子句的文档都会被返回。
这个参数可以接收绝对数值(如 2
)、百分比(如 30%
)、和组合(如 3<90%
表示至少匹配3个或者90%,取其中较大的那个)等不同类型的值。
注意:如果 bool
查询中只有 should
子句(没有 must
或 filter
),那么默认情况下至少需要匹配一个 should
条件,也就是minimum_should_match
默认值是1,除非 minimum_should_match
明确设定为其他值。如果包含 must
或 filter
的情况下minimum_should_match
默认值 0。
所以我们可以在包含 must
或 filter
的情况下,设置 minimum_should_match
值来满足 should
子句中的条件。
Boosting查询
返回匹配 positive
(肯定) 查询的文档,同时降低匹配 negative
(否定) 查询的文档的相关性评分。
可以使用 boosting
查询来降级某些文档(降低其相关性评分),但不会将它们从搜索结果中排除。
请求示例
GET /_search
{"query": {"boosting" : {"positive" : {"term" : {"text" : "apple"}},"negative" : {"term" : {"text" : "pie tart fruit crumble tree"}},"negative_boost" : 0.5}}
}
用于 Boosting
的顶级参数
positive
(必需的, query 对象) 你想运行的查询。 任何返回的文档都必须与该查询匹配。negative
(必需的, query 对象) 用于降低匹配文档的 相关性评分的查询。如果返回的文档匹配positive
查询和该查询,则boosting
查询像下面这样计算该文档的最终相关性评分 :从positive
查询中获取原始相关性评分。将该分数值乘以negative_boost
值。negative_boost
(必需的, float) 一个介于0
和1.0
之间的浮点数,用于降低与negative
查询匹配的文档的相关性评分。
constant_score 查询
包裹一个 filter 查询并返回每个匹配的文档,其相关性评分等于参数 boost
的值。
GET /_search
{"query": {"constant_score" : {"filter" : {"term" : { "user" : "kimchy"}},"boost" : 1.2}}
}
constant_score
的顶级参数
filter
(必需的, query 对象) 你想运行的 filter 查询。 任何返回的文档都必须匹配此查询。filter 查询不会计算相关性评分。 为了提高性能,ElasticSearch 会自动缓存常用的 filter 查询。boost
(可选, float) 用于匹配filter
查询的每个文档的常量相关性评分的浮点数。 默认值为1.0
。
dis_max (disjunction max) 查询
译者注:
disjunction max, 通俗解释为: 多个之间取或的最大值。
将任何域任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回。
返回匹配一个或多个被包裹的查询(称为查询子句或子句)的文档。
如果一个返回的文档匹配多个查询子句,dis_max
查询将为该文档分配任何匹配子句中的最高相关性评分,并为任何其他匹配子查询分配一个打破平局的增量。
可以使用 dis_max
在映射了不同 Boost 因子的字段中搜索一个 词项(term)。
请求示例
GET /_search
{"query": {"dis_max" : {"queries" : [{ "term" : { "title" : "Quick pets" }},{ "term" : { "body" : "Quick pets" }}],"tie_breaker" : 0.7}}
}
dis_max
的顶级参数
queries
(必需的, query 对象数组) 包含一个或多个查询字句。 返回的文档 必须匹配这些查询中的一个或多个。 如果一个文档与多个查询匹配,ElasticSearch 会采用最高的那个相关性评分。tie_breaker
(可选, float)0
到1.0
之间的浮点数,用于增加匹配多个查询子句的文档的相关性评分。 默认值为0.0
。可以使用tie_breaker
值为多个字段中包含相同词项(term)的文档指定比仅在这些字段中最好的字段中包含该词项的文档更高的相关性评分,而不会将其与多个字段中两个不同术语的更好情况混淆。(这一句的翻译比较烂...)如果一个文档匹配多个子句,dis_max
查询将计算该文档的相关性评分,计算方法如下:从得分最高的匹配子句中取相关性评分。将任何其他匹配子句的分数乘以tie_breaker
值。将最高分与相乘后的分数相加。如果tie_breaker
的值大于0.0
,则所有匹配的子句都会计算在内,但分数最高的子句计算最多。
function_score (函数评分) 查询
function_score
允许你修改查询检索到的文档的分数。 例如,如果一个评分函数的计算开销很大,并且它足以计算经过筛选的一组文档的分数,那么这就很有用了。
要使用 function_score
,用户必须定义一个查询和一个或多个函数,这些函数为查询返回的每个文档计算一个新分数。
function_score
只能用于一个函数,如下所示:
GET /_search
{"query": {"function_score": {"query": { "match_all": {} },"boost": "5","random_score": {}, "boost_mode":"multiply"}}
}
- 受支持的函数列表请参考函数评分。
此外,几个功能可以组合。在这种情况下,我们可以选择只在文档匹配指定的 filter 查询时应用该函数。
GET /_search
{"query": {"function_score": {"query": { "match_all": {} },"boost": "5", "functions": [{"filter": { "match": { "test": "bar" } },"random_score": {}, "weight": 23},{"filter": { "match": { "test": "cat" } },"weight": 42}],"max_boost": 42,"score_mode": "max","boost_mode": "multiply","min_score" : 42}}
}
- 整个查询的提高(boost)。
- 受支持的函数列表请参考函数评分。
每个函数的 filter 查询产生的分数并不重要。
如果函数中没有给出任何 filter,这相当于指定 "match_all": {}
。
首先,每个文档由定义的函数评分。 参数 score_mode
指定如何组合计算出的分数:
参数 | 含义 |
---|---|
multiply |
分数相乘(默认) |
sum |
分数相加,求和 |
avg |
分数的平均值 |
first |
应用第一个具有匹配 filter 的函数 |
max |
取分数最大值 |
min |
取分数最小值 |
因为分数可以在不同的范围内(例如,衰减函数(decay function)在0到1之间,而 field_value_factor
是任意的),而且有时函数对分数的不同影响是可取的,所以可以使用用户定义的 weight
(权重) 来调整每个函数的分数。 weight
可以在 functions
数组(上面的例子)中按每个函数定义,并与相应函数计算的分数相乘。 如果给定 weight 时没有任何其他函数声明,weight
就会作为一个函数返回weight
。
如果 score_mode
被设置为 avg
,则单个分数将被 weighted(加权) 平均。 例如,如果两个函数返回 1 和 2 分,它们各自的权重分别为 3 和 4,那么它们的得分将合并为 (1*3+2*4)/(3+4)
而不是 (1*3+2*4)/2
。
通过设置 max_boost
参数,可以限制新的分数不超过某个限制。 max_boost
的默认值是 FLT_MAX。
新计算的分数与查询的分数相结合。 参数 boost_mode
定义了如何操作:
参数 | 含义 |
---|---|
multiply |
查询分数和函数分数相乘(默认) |
replace |
只使用函数分数,而忽略查询分数 |
sum |
查询分数和函数分数相加 |
avg |
平均值 |
max |
查询分数和函数分数的最大值 |
min |
查询分数和函数分数的最小值 |
默认情况下,修改分数不会改变匹配的文档。 要排除不满足某个分数阈值的文档,可以将参数 min_score
设置为所需的分数阈值。
要让 min_score
起作用,需要对查询返回的所有文档进行评分,然后逐一过滤掉。
function_score
查询提供了以下几种评分函数。
script_score
weight
random_score
field_value_factor
- 衰减函数 (decay function):
gauss
,linear
,exp
脚本评分 (Script score)
script_score
函数允许包裹另一个查询,并使用脚本表达式使用从文档中的其他 数值(numeric) 字段值派生的计算定制该查询的评分。 这里是一个简单的例子:
GET /_search
{"query": {"function_score": {"query": {"match": { "message": "ElasticSearch" }},"script_score" : {"script" : {"source": "Math.log(2 + doc['likes'].value)"}}}}
}
在 ElasticSearch 中,所有文档的评分都是一个 32 位的浮点数。
如果script_score
函数生成了一个精度更高的分数,那么它将被转换为最接近的 32 位浮点数。
同样,分数必须是非负的。 否则,ElasticSearch 返回一个错误。
在不同的脚本字段值和表达式之上,可以使用 _score
脚本参数根据包裹的查询来检索分数。
脚本编译被缓存以更快地执行。 如果脚本有需要考虑的参数,最好重用同一个脚本,并为其提供 params
(参数):
GET /_search
{"query": {"function_score": {"query": {"match": { "message": "ElasticSearch" }},"script_score" : {"script" : {"params": {"a": 5,"b": 1.2},"source": "params.a / Math.pow(params.b, doc['likes'].value)"}}}}
}
请注意,与 custom_score
查询不同,查询的分数会乘以脚本评分的结果。 如果你希望禁止这种情况,请设置 "boost_mode": "replace"
。
权重 (weight)
weight
分数允许你将分数乘以指定的 weight
值。 这有时是需要的,因为在特定查询上设置的 boost(提升)值 被归一化了,而对于这个评分函数却没有。 number 值的类型是 float。
"weight" : number
随机 (random)
random_score
生成从 0 到 1 (不包括1) 均匀分布的分数。 默认情况下,它使用内部 Lucene 文档 id 作为随机数种子(seed),这非常有效,但不幸的是不可再现的,因为文档可能会被合并而重新编号。
如果你希望分数是可再现的,可以提供一个 seed
(种子) 和 field
(字段)。 然后,将基于该种子、所考虑文档的 field
(字段) 的最小值以及基于索引名称和分片id计算的 盐(salt) 来计算最终得分,以便具有相同值但存储在不同索引中的文档获得不同的得分。 请注意,在同一个分片中并且具有相同 field
值的文档将获得相同的分数,因此通常希望对所有文档使用具有唯一值的字段。 一个好的默认选择可能是使用 _seq_no
字段,其唯一的缺点是如果文档被更新,分数将会改变,因为更新操作也会更新 _seq_no
字段的值。
可以在不设置字段的情况下设置种子,但这已被废弃,因为这需要在
_id
字段上加载 fielddata(字段的数据),这会消耗大量内存。
GET /_search
{"query": {"function_score": {"random_score": {"seed": 10,"field": "_seq_no"}}}
}
字段值因子 (field value factor)
field_value_factor
函数允许你使用文档中的字段来影响分数。 它类似于使用 script_score
函数,但是它避免了脚本的开销。 如果用于 多值(multi-valued) 字段,则计算中仅使用字段的第一个值。
例如,假设你有一个用数字 likes
字段索引的文档,并希望用该字段影响文档的评分,以下就是一个示例:
GET /_search
{"query": {"function_score": {"field_value_factor": {"field": "likes","factor": 1.2,"modifier": "sqrt","missing": 1}}}
}
上面的代码将转化为以下评分公式:
sqrt(1.2 * doc['likes'].value)
函数 field_value_factor
有多个选项:
参数 | 含义 |
---|---|
field |
要从文档中提取的字段。 |
factor |
与字段值相乘的可选因子,默认值为 1 。 |
modifier |
应用于字段值的修饰符,可以是下列值之一:none 、log 、log1p 、log2p 、ln 、ln1p 、ln2p 、square 、sqrt 或 reciprocal 。 默认值为 none 。 |
修饰符 | 意义 |
---|---|
none |
不要对字段值应用任何乘数 |
log |
取字段值的常用对数(common logarithm)。 由于该函数用于 0 到 1 之间的值时会返回负值,这会导致错误,所以建议使用 log1p 以代替之。 |
log1p |
将字段值加 1,取常用对数 |
log2p |
将字段值加 2,取常用对数 |
ln |
取字段值的自然对数(natural logarithm)。 由于该函数用于 0 到 1 之间的值时会返回负值,这会导致错误,因此建议使用 ln1p 以代替之。 |
ln1p |
将字段值加 1,取自然对数 |
ln2p |
将字段值加 2,取自然对数 |
square |
字段值的平方(乘以它本身) |
sqrt |
取字段值的平方根(square root) |
reciprocal |
字段值的倒数(reciprocate),与 1/x 相同,其中 x 是字段的值 |
missing
文档没有该字段时使用的值。 修饰符和因子仍然应用于它,就好像它是从文档中读取的一样。
field_value_score
函数生成的分数值必须是非负的,否则将会引起错误。 如果log
和ln
修饰符用于 0 到 1 之间的值,将产生负值。 确保使用范围过滤器限制字段的值以避免这种情况,或者使用log1p
和ln1p
。
请记住,取 0 的 log() 或 负数的平方根是非法操作,将会引发异常。 确保使用范围过滤器限制字段的值以避免这种情况,或者使用log1p
和ln1p
。
衰减函数 (decay functions)
衰减函数(decay functions) 使用根据文档的数值字段值与用户给定原点的距离衰减的函数对文档进行评分。 这类似于 范围查询(range query),但是使用平滑的边缘而不是方框。
要对具有数值字段的查询使用距离评分,用户必须为每个字段定义 origin
(原点)和 scale
(范围)。 需要使用 origin
(原点) 来定义计算距离的“中心点”,使用 scale
(范围) 来定义衰减率。 衰减函数可以这样定义:
"DECAY_FUNCTION": { "FIELD_NAME": { "origin": "11, 12","scale": "2km","offset": "0km","decay": 0.33}
}
DECAY_FUNCTION
应为linear
、exp
或gauss
。- 指定的字段必须是 numeric、date 或 geo-point 类型的。
在上面的例子中,字段是geo_point
类型,origin 可以以 geo 格式提供。 在这种情况下,scale
和offset
必须使用上例中的单位。 如果你的字段是 date 类型,可以将scale
和offset
设置为天(d)、周(w)等。 示例:
GET /_search
{"query": {"function_score": {"gauss": {"date": {"origin": "2013-09-17", "scale": "10d","offset": "5d", "decay" : 0.5 }}}}
}
- origin 的日期格式取决于 mapping 中定义的
format
(格式)。 如果没有定义origin,则使用当前时间。 - 参数
offset
和decay
是可选的。
参数 | 含义 |
---|---|
origin |
用于计算距离的原点。 对于 numeric 字段,必须以数字形式给出;对于 date 字段,必须以日期形式给出;对于 geo 段,必须以地理点形式给出。 对于 geo 和 numeric 字段是必需的。 对于 date 字段,默认值为 now (现在)。 原点支持日期计算(例如 now-1h )。 |
scale |
所有类型都需要。 定义从 origin + offset 的距离,在该距离处计算的分数将等于参数 decay 。 对于 geo 字段:可以定义为 数字 + 单位(如:"1km","12m",...),默认单位是 m (米)。 对于 date 字段:可以定义为 数字 + 单位(如:"1h","10d"...),默认单位是 ms (毫秒)。 对于 numeric 字段: 可以是任意数值。 |
offset |
如果定义了 offset ,衰减函数将只计算距离大于定义的 offset 的文档衰减。 默认值为 0 。 |
decay |
参数 decay 定义了如何在 scale 给定的距离上对文档进行评分。 如果没有定义 decay ,则在 scale 距离上的文档将被评分为 0.5 。 |
在第一个例子中,文档可能表示酒店并包含 geo(地理位置) 字段。 你希望根据酒店离给定位置的距离来计算衰减函数。 你可能不会立即看到为 guass(高斯)函数 选择哪一个 scale,但是你可以这样说:“在距离期望位置 2km 处,分数应减少到三分之一。” 然后将自动调整参数"scale",以确保评分函数计算出距离期望位置 2km 的酒店的分数为0.33。
在第二个例子中,字段值在 2013-09-12 和 2013-09-22 之间的文档的权重(weight)为 1.0,距离该日期超过 15 天的文档的权重为 0.5。
支持的衰减函数
DECAY_FUNCTION
决定衰减的形状:
gauss
正态衰减,计算如下:其中,要计算以确保分数在距离origin
+-offset
的scale
距离处取值为decay
:有关gauss
函数生成的曲线的图形的演示,请参考正态衰减,关键字gauss
。exp
指数衰减,计算如下:其中,参数再次被计算以确保分数在距离origin
+-offset
的scale
距离处取值为decay
:有关exp
函数生成的曲线的图形的演示,请参考 指数衰减,关键字exp
。linear
线性衰减,计算如下:.其中,参数s
再次被计算以确保分数在距离origin
+-offset
的scale
距离处取值为decay
:与正态和指数衰减相反,如果字段值超过用户给定 scale 值的两倍,此函数实际上将分数设置为 0。
对于单个函数,三个衰减函数以及它们的参数可以像下面这样可视化(在这个例子中称为 “age”(年龄) 的字段):
多值字段 (multi-values fields)
如果用于计算衰减的字段包含多个值,默认情况下会选择最接近原点(origin)的值来确定距离。 这可以通过设置 multi_value_mode
来改变。
参数 | 含义 |
---|---|
min |
取最小距离作为距离值 |
max |
取最大距离作为距离值 |
avg |
取平均距离作为距离值 |
sum |
取所有距离的和作为距离值 |
示例:
"DECAY_FUNCTION": {"FIELD_NAME": {"origin": ...,"scale": ...},"multi_value_mode": "avg"}
详细示例
假如你正在某个城市寻找一家酒店,而你的预算有限。 此外,你希望酒店靠近市中心,因此酒店离理想位置越远,入住的可能性就越小。
你希望匹配你的标准(例如,“hotel, Nancy, non-smoker”)的查询结果根据到市中心的距离以及价格进行评分。
直觉上,你可能希望将市中心定义为起点,并且可能愿意从酒店步行 2km 到市中心。
在这种情况下,位置字段的 origin 是城镇中心,scale 为 2km。
如果你的预算很低,你可能更喜欢便宜的东西而不是贵的东西。 对于 price(价格) 字段, origin 为 0 欧元,scale 取决于你愿意支付的金额,例如 20 欧元。
在本例中,对于酒店的价格,字段可能被称为 "price",而对于该酒店的坐标,字段可能被称为 "location"。
在这种情况下, price
的函数是:
"gauss": { "price": {"origin": "0","scale": "20"}
}
- 这个衰减函数也可以是
linear
或exp
。
对于location
:
"gauss": { "location": {"origin": "11, 12","scale": "2km"}
}
- 这个衰减函数也可以是
linear
或exp
。
假设你想将这两个函数在原始分数上相乘,则请求如下所示:
GET /_search
{"query": {"function_score": {"functions": [{"gauss": {"price": {"origin": "0","scale": "20"}}},{"gauss": {"location": {"origin": "11, 12","scale": "2km"}}}],"query": {"match": {"properties": "balcony"}},"score_mode": "multiply"}}
}
接下来,我们展示了三种可能的衰减函数的计算分数。
正态衰减,关键字 gauss
在上面的示例中,当选择 gauss
作为衰减函数时,乘数的等高线和曲面图如下所示:
假设原始搜索结果匹配三家酒店:
- "Backback Nap"
- "Drink n Drive"
- "BnB Bellevue"
"Drink n Drive" 离你定义的位置相当远(将近 2km),而且不太便宜(约 13 欧元),所以它的因子很低,为 0.56。 "BnB Bellevue"和"Backback Nap"都非常接近定义的位置,但"BnB Bellevue"更便宜,因此它的因子为 0.86,而"Backpack Nap"的因子值为 0.66。
指数衰减,关键字 exp
在上面的示例中,当选择 exp
作为衰减函数时,乘数的等高线和曲面图如下所示:
线性衰减,关键字 linear
在上面的示例中,当选择 linear
作为衰减函数时,乘数的等高线和曲面图如下所示:
衰减函数支持的字段
只支持 numeric、date 和 geo-point 字段。
如果一个字段缺失,怎么办?
如果文档中缺少 numeric 字段,该函数将返回 1。
联结查询 (joining queries)
在像 ElasticSearch 这样的分布式系统中执行完全 SQL 风格的联结(join)的成本是非常高的。 相反,ElasticSearch 提供了两种水平扩展的联结形式。
nested
(嵌套) 查询
文档可能包含nested
(嵌套) 类型的字段。 这些字段用于索引对象数组,其中每个对象都可以作为独立的文档进行查询(使用nested
查询)。has_child
和has_parent
查询
单个索引中的文档之间可以存在join
字段关系。has_child
查询返回其子文档与指定查询匹配的父文档,而has_parent
查询返回其父文档与指定查询匹配的子文档。
另请参考terms
查询中的词项查找机制,它允许你从另一个文档中包含的值构建terms
查询。
嵌套(nested)查询
包裹另一个查询以搜索nested(嵌套)字段。
nested
查询搜索嵌套的字段对象,就好像它们被索引为单独的文档一样。 如果对象与搜索匹配,nested
查询将返回根父文档。
请求示例
准备一个索引
若要使用nested
查询,索引必须包含nested字段映射。例如:
PUT /my_index
{"mappings" : {"properties" : {"obj1" : {"type" : "nested"}}}
}
查询示例
GET /my_index/_search
{"query": {"nested" : {"path" : "obj1","query" : {"bool" : {"must" : [{ "match" : {"obj1.name" : "blue"} },{ "range" : {"obj1.count" : {"gt" : 5}} }]}},"score_mode" : "avg"}}
}
nested
的顶级参数
path
(必需, string) 要搜索的嵌套对象的路径。query
(必需, query object) 要在指定的path
中的嵌套对象上运行的查询。 如果一个对象与搜索匹配,nested
查询将返回根父文档。可以使用包含完整路径的点符号来搜索嵌套字段,例如obj1.name
。自动支持和检测多级嵌套,导致内部嵌套查询自动匹配相关的嵌套层级,而不是根(如果它存在于另一个嵌套查询中)。-- TODO 待根据后面的内容修正 Multi-level nesting is automatically supported, and detected, resulting in an inner nested query to automatically match the relevant nesting level, rather than root, if it exists within another nested query.有关示例请参考多级嵌套查询。score_mode
(可选, string) 指示匹配子对象的分数如何影响根父文档的相关性评分。有效值有:avg
(默认) 使用所有匹配子对象的相关性评分的平均分。max
使用所有匹配子对象的相关性评分的最高分。min
使用所有匹配子对象的相关性评分的最低分。none
不使用匹配子对象的相关性评分。该查询为父文档分配的分数为0
。sum
将所有匹配子对象的相关性评分相加。ignore_unmapped
(可选, boolean) 指示是否忽略未映射的path
并且不返回任何文档而不是错误。默认为false
。如果设置为false
,则当path
是未映射的字段时,ElasticSearch 会抛出错误。可以使用此参数来查询可能不包含path
路径的多个索引。
注意
多级嵌套查询 (multi-level nested queries)
要了解多级嵌套查询是如何工作的,首先你需要一个包含嵌套字段的索引。 下面这个请求定义了具有嵌套字段make
和model
的名为drivers
的索引的映射。
PUT /drivers
{"mappings" : {"properties" : {"driver" : {"type" : "nested","properties" : {"last_name" : {"type" : "text"},"vehicle" : {"type" : "nested","properties" : {"make" : {"type" : "text"},"model" : {"type" : "text"}}}}}}}
}
接下来,添加并索引几个文档到索引drivers
中:
# 添加第1个文档,指定id为1
PUT /drivers/_doc/1
{"driver" : {"last_name" : "McQueen","vehicle" : [{"make" : "Powell Motors","model" : "Canyonero"},{"make" : "Miller-Meteor","model" : "Ecto-1"}]}
}# 添加第2个文档,指定id为2
PUT /drivers/_doc/2?refresh
{"driver" : {"last_name" : "Hudson","vehicle" : [{"make" : "Mifune","model" : "Mach Five"},{"make" : "Miller-Meteor","model" : "Ecto-1"}]}
}
现在,你可以使用多级嵌套查询来根据make
和model
字段匹配文档:
GET /drivers/_search
{"query" : {"nested" : {"path" : "driver","query" : {"nested" : {"path" : "driver.vehicle","query" : {"bool" : {"must" : [{ "match" : { "driver.vehicle.make" : "Powell Motors" } },{ "match" : { "driver.vehicle.model" : "Canyonero" } }]}}}}}}
}
搜索请求返回如下响应:
{"took" : 5,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 3.7349272,"hits" : [{"_index" : "drivers","_type" : "_doc","_id" : "1","_score" : 3.7349272,"_source" : {"driver" : {"last_name" : "McQueen","vehicle" : [{"make" : "Powell Motors","model" : "Canyonero"},{"make" : "Miller-Meteor","model" : "Ecto-1"}]}}}]}
}
has_child 查询
返回与其联结的(joined)且匹配查询的子文档的父文档。 可以使用 join 字段映射在同一索引中的文档之间创建父子关系。
因为它要执行联结,所以与其他查询相比,has_child
比较慢。 随着指向唯一父文档的匹配的子文档数量的增加,其性能会下降。 搜索中的每个has_child
查询都会显著地增加查询时间。
如果你在乎查询性能,请不要使用此查询。 如果你确实需要使用has_child
查询,请尽量少用。
请求示例
创建索引
若要使用has_child
查询,索引中必须包含 join 字段映射。例如:
PUT /my_index
{"mappings": {"properties" : {"my-join-field" : {"type" : "join","relations": {"parent": "child"}}}}
}
查询示例
GET /_search
{"query": {"has_child" : {"type" : "child","query" : {"match_all" : {}},"max_children": 10,"min_children": 2,"score_mode" : "min"}}
}
has_child
的顶级参数
type
(必需, string) 为 join 字段映射的子关系的名称。query
(必需, query object) 希望在type
字段的子文档上运行的查询。如果子文档与搜索匹配,查询将返回父文档。ignore_unmapped
(可选, boolean) 指示是否忽略未映射的type
并且不返回任何文档而不是错误。默认为false
。如果为false
,当type
未映射时 ElasticSearch 会返回错误。可以使用此参数来查询可能不包含type
的多个索引。max_children
(可选, integer) 允许的返回的父文档中与query
相匹配的子文档的最大数量。 如果父文档中的与该查询匹配的子文档的数量超过此数量,它将从搜索结果中排除。min_children
(可选, integer) 允许的返回的父文档中与query
相匹配的子文档的最小数量。 如果父文档中的与该查询匹配的子文档的数量未达到此数量,它将从搜索结果中排除。score_mode
(可选, string) 指示匹配子文档的分数如何影响根父文档的相关性评分。有效值有:none
(默认) 不使用匹配子文档的相关性分数。该查询为父文档分配0
分。avg
取所有匹配子文档的相关性分数的平均值。max
取所有匹配子文档的相关性分数的最大值。min
取所有匹配子文档的相关性分数的最小值。sum
把所有匹配子文档的相关性分数相加。
注意
排序
不能使用标准排序选项对 has_child
查询的结果进行排序。
如果需要按子文档中的字段对返回的文档进行排序,请使用 function_score
查询并按 _score
排序。 例如,下面这个查询按子文档的 click_count
字段对返回的文档进行排序:
GET /_search
{"query": {"has_child" : {"type" : "child","query" : {"function_score" : {"script_score": {"script": "_score * doc['click_count'].value"}}},"score_mode" : "max"}}
}
has_parent 查询
返回与其联结的(joined)且匹配查询的父文档的子文档。 可以使用 join 字段映射在同一索引中的文档之间创建父子关系。
因为它要执行联结,所以与其他查询相比,has_parent
比较慢。 随着匹配父文档数量的增加,其性能会下降。 搜索中的每个has_parent
查询都会显著地增加查询时间。
请求示例
创建索引
要使用 has_parent
查询,索引必须包含 join 字段映射。例如:
PUT /my-index
{"mappings": {"properties" : {"my-join-field" : {"type" : "join","relations": {"parent": "child"}},"tag" : {"type" : "keyword"}}}
}
查询示例
GET /my-index/_search
{"query": {"has_parent" : {"parent_type" : "parent","query" : {"term" : {"tag" : {"value" : "ElasticSearch"}}}}}
}
has_parent
的顶级参数
parent_type
(必需, string) 为 join 字段映射的父关系的名称。query
(必需, query object) 希望在parent_type
字段的父文档上运行的查询。如果父文档与搜索匹配,查询将返回子文档。score
(可选, boolean) 指示匹配父文档的相关性评分是否聚合到其子文档中。默认为false
。如果为false
,ElasticSearch 将忽略父文档的相关性评分。 ElasticSearch 还为每个子文档分配一个与query
的boost
值相等的相关性评分,默认为1
。如果为true
,则匹配父文档的相关性评分被聚合到其子文档的相关性评分中。ignore_unmapped
(可选, boolean) 指示是否忽略未映射的parent_type
并且不返回任何文档而不是错误。默认为false
。如果为false
,当parent_type
未映射时 ElasticSearch 会返回错误。可以使用此参数来查询可能不包含parent_type
的多个索引。
注意
排序
不能使用标准排序选项对 has_parent
查询的结果进行排序。
如果需要按父文档中的字段对返回的文档进行排序,请使用 function_score
查询并按 _score
排序。 例如,下面这个查询按父文档的 view_count
字段对返回的文档进行排序:
GET /_search
{"query": {"has_parent" : {"parent_type" : "parent","score" : true,"query" : {"function_score" : {"script_score": {"script": "_score * doc['view_count'].value"}}}}}
}
parent_id 查询
返回联结(joined)到指定父文档的子文档。 可以使用 join 字段映射在同一索引中的文档之间创建父子关系。
请求示例
创建索引
要使用 parent_id
查询,索引必须包含 join 字段映射。 若要查看如何为 parent_id
查询创建索引,请尝试下面这个例子。
- 创建一个使用了 join 字段映射的索引:
PUT /my-index
{"mappings": {"properties" : {"my-join-field" : {"type" : "join","relations": {"my-parent": "my-child"}}}}
}
- 添加并索引一个ID为
1
的父文档:
PUT /my-index/_doc/1?refresh
{"text": "This is a parent document.","my-join-field": "my-parent"
}
- 添加并索引一个该父文档的子文档,ID为
2
:
PUT /my-index/_doc/2?routing=1&refresh
{"text": "This is a child document.","my_join_field": {"name": "my-child","parent": "1"}
}
查询示例
下面这个搜索返回 ID 为 1
的父文档的子文档:
GET /my-index/_search
{"query": {"parent_id": {"type": "my-child","id": "1"}}
}
parent_id
的顶级参数
type
(必需, string) 为 join 字段映射的子关系的名称。id
(必需, string) 父文档的ID。查询会返回该父文档的子文档。ignore_unmapped
(可选, boolean) 指示是否忽略未映射的type
并且不返回任何文档而不是错误。默认为false
。如果为false
,当type
未映射时 ElasticSearch 会返回错误。可以使用此参数来查询可能不包含type
的多个索引。
注意
允许执行昂贵的查询
如果 search.allow_expensive_queries
设置为false
,将不会执行联结查询。
跨度查询(span)
跨度(span)查询是低级的位置查询,它提供对指定词项的顺序和接近度的专家级控制。 这些通常用于实现对法律或专利文档的非常具体的查询。
只允许在外部 span 查询上设置增强(boost)。 复合 span 查询,如span_near
,只使用内部 span 查询的匹配的 span 列表,以便找到它们自己的 span,然后使用这些 span 来产生评分。 从不在内部 span 查询上计算分数,这就是不允许使用增强(boost)的原因是:它们只影响分数的计算方式,而不影响 span。
span查询不能与非span查询混合使用( span_multi
查询除外)。
这组查询有:
span_containing
查询
接受一个 span 查询的列表,但只返回与第二个 span 查询相匹配的 span。field_masking_span
查询
允许跨不同字段的查询,如span-near
或span-or
。span_first
查询
接受另一个 span 查询,且该查询的匹配必须出现在字段的前 N 个位置。span_multi
查询
包裹一个term
、range
、prefix
、wildcard
、regexp
或fuzzy
查询。span_near
查询
接受多个 span 查询,这些查询的匹配必须、且可能以相同的顺序出现在彼此的指定距离内。span_not
查询
包裹另一个 span 查询,并排除任何匹配该查询的文档。span_or
查询
组合多个 span 查询 — 返回与任何指定查询匹配的文档。span_term
查询
相当于term
查询,但与其他 span 查询一起使用。 other span queries.span_within
查询
只要单个 span 查询的 span 在其他 span 查询列表返回的 span 内,就会返回该 span 查询的结果。
span_containing 查询
返回包含另一个 span 查询的匹配。 span 包含查询对应 Lucene 的 SpanContainingQuery
。这里有一个例子:
GET /_search
{"query": {"span_containing" : {"little" : {"span_term" : { "field1" : "foo" }},"big" : {"span_near" : {"clauses" : [{ "span_term" : { "field1" : "bar" } },{ "span_term" : { "field1" : "baz" } }],"slop" : 5,"in_order" : true}}}}
}
big
和 little
子句可以是任何 span 类型的查询。 返回 big
中包含 little
中匹配项的匹配的 span。
field_masking_span 查询
包装器(wrapper),允许 span 查询通过谎报其搜索字段来参与复合单字段的 span 查询。 span 字段遮盖(masking)查询对应 Lucene 的 SpanFieldMaskingQuery
。
这可以用来支持 span-near
或 span-or
跨不同字段的查询,而这通常是不允许的。
当使用多个分析器对相同的内容进行索引时,span 字段遮盖查询与多字段(multi-fields) 结合使用是非常宝贵的。 例如,我们可以用 standard 分析器将文本分解成单词,再用 english 分析器将单词词干化成词根形式来索引字段。
示例:
GET /_search
{"query": {"span_near": {"clauses": [{"span_term": {"text": "quick brown"}},{"field_masking_span": {"query": {"span_term": {"text.stems": "fox"}},"field": "text"}}],"slop": 5,"in_order": false}}
}
注意:当 span 字段遮盖查询返回遮盖字段时,将使用提供的字段名的规范进行评分。 这可能会导致意外的评分行为。
span_first 查询
匹配字段开头附近的 span。 span_first 查询对应 Lucene 的 SpanFirstQuery
。 这里有一个例子:
GET /_search
{"query": {"span_first" : {"match" : {"span_term" : { "user" : "kimchy" }},"end" : 3}}
}
match
子句可以是任何其他 span 类型的查询。 end
控制匹配中允许的最大终点位置。
span_multi 查询
span_multi
查询允许你将多词项查询
(通配符 wildcard、模糊 fuzzy、前缀 prefix、范围 range 或 正则 regexp 查询之一) 包装为 span 查询
,因此它可以嵌套。 示例:
GET /_search
{"query": {"span_multi":{"match":{"prefix":{"user":{"value":"ki"}}}}}
}
增强(boost)也可以与查询相关联:
GET /_search
{"query": {"span_multi":{"match":{"prefix":{"user":{"value":"ki","boost":1.08}}}}}
}
如果匹配查询的词项的数量超过 bool 查询限制(默认为1024),
span_multi
查询将会遇到太多子句失败。 为了避免无限制的扩展,可以将多项查询的重写方法设置为top_terms_*
重写。 或者,如果仅对prefix
查询使用span_multi
,则可以激活text
字段的index_prefixes
字段选项。 这将把字段上的任何前缀查询重写为与索引前缀匹配的单个词项查询。
span_near 查询
匹配彼此靠近的 span。 可以指定slop(插入不匹配位置的最大数量),以及 in_order(匹配是否需要有序)。 span_near 查询对应 Lucene 的 SpanNearQuery
。这里有一个例子:
GET /_search
{"query": {"span_near": {"clauses":[{"span_term":{"field": "value1"}},{"span_term":{"field": "value2"}},{"span_term":{"field": "value3"}}],"slop": 12,"in_order": false}}
}
clauses
元素是一个或多个其他 span 类型查询的列表,slop
控制允许的中间不匹配位置的最大数量。
span_not 查询
删除与另一个 span 查询重叠的匹配项,或者位于另一个 span 查询之前的 x 标记(由参数 pre
控制) 或 之后的 y 标记(由参数 post
控制) 内的匹配项。 span_not 查询对应 Lucene 的 SpanNotQuery
。这里有一个例子:
GET /_search
{"query": {"span_not": {"include": {"span_term": {"field1": "hoya"}},"exclude": {"span_near": {"clauses": [{"span_term": {"field1": "la"}},{"span_term": {"field1": "hoya"}}],"slop": 0,"in_order": true}}}}
}
include
和 exclude
子句可以是任何 span 类型的查询。 include
子句是过滤匹配项的 span 查询,exclude
子句是匹配项不能与返回项重叠的 span 查询。
在上面的例子中,除了前面有la的文档之外,所有带有hoya的文档都被过滤了。
其他顶级选项有:
选项 | 含义 |
---|---|
pre |
如果设置了,则包含 span 之前的词元数量不能与 exclude span 重叠。 默认值为 0。 |
post |
如果设置了,则包含 span 后的词元数量不能与 exclude span 重叠。 默认值为 0。 |
dist |
如果设置了,包含 span 内的词元数量不能与 exclude span 重叠。 相当于设置了 pre 和 post 。 |
span_or 查询
匹配其 span 子句的并集。它对应 Lucene 的 SpanOrQuery
。这里有一个例子:
GET /_search
{"query": {"span_or" : {"clauses" : [{ "span_term" : { "field" : "value1" } },{ "span_term" : { "field" : "value2" } },{ "span_term" : { "field" : "value3" } }]}}
}
clauses
元素是一个或多个其他 span 类型查询的列表。
span_term 查询
匹配包含指定词项的 span。它对一个 Lucene 的 SpanTermQuery
。这里是一个例子:
GET /_search
{"query": {"span_term" : { "user" : "kimchy" }}
}
增强(boost)也可以与查询相关联:
GET /_search
{"query": {"span_term" : { "user" : { "value" : "kimchy", "boost" : 2.0 } }}
}
或者:
GET /_search
{"query": {"span_term" : { "user" : { "term" : "kimchy", "boost" : 2.0 } }}
}
span_within 查询
返回包含在另一个 span 查询中的匹配项。 它对应 Lucene 的 SpanWithinQuery
。 这里是一个例子:
GET /_search
{"query": {"span_within" : {"little" : {"span_term" : { "field1" : "foo" }},"big" : {"span_near" : {"clauses" : [{ "span_term" : { "field1" : "bar" } },{ "span_term" : { "field1" : "baz" } }],"slop" : 5,"in_order" : true}}}}
}
big
和 little
子句可以是任何 span 类型的查询。 返回包含在 big
中的 little
的匹配 span。
词级查询 (term-level query)
可以使用词级查询,根据结构化数据中的精确值来查找文档。 结构化数据的例子包括日期范围、IP地址、价格或产品 id。
与全文查询不同,词级查询不分析用于搜索的词项。 相反,词级查询与存储在字段中的确切词项相匹配。
词级查询仍然使用 normalizer
属性对 keyword
字段的搜索词项进行归一化。 有关信息请参考 normalizer
。
词项级别查询的类型
exists
查询
返回包含任何字段索引值的文档。fuzzy
查询
返回包含与搜索词项相似的词项的文档。 ElasticSearch 使用莱温斯坦编辑距离]来度量相似性或模糊性。ids
查询
根据文档 id 返回文档。prefix
查询
返回在指定的字段中包含特定前缀的文档。range
查询
返回包含给定范围内的词项的文档。regexp
查询
返回包含匹配正则表达式的词项的文档。term
查询
返回在指定的字段中包含精确词项的文档。terms
查询
返回在指定的字段中包含一个或多个精确词项的文档。terms_set
查询
返回在指定的字段中包含最少数量精确词项的文档。 可以使用字段或脚本定义匹配词项的最小数量。type
查询
返回指定类型的文档。wildcard
查询
返回包含匹配通配符模式的词项的文档。
exists 查询
返回包含一个字段索引值的文档。
由于各种原因,文档的字段可能不存在索引值:
- 源 JSON 中的字段为
null
或[]
- 字段在映射中有
"index" : false
的设置 - 字段值的长度超过了映射中的
ignore_above
设置 - 字段值格式不正确,并且在映射中定义了
ignore_malformed
请求示例
GET /_search
{"query": {"exists": {"field": "user"}}
}
exists
的顶级参数
field
(必须, string) 你想要搜索的字段的名称。如果 JSON 值为null
或[]
,则字段被视为不存在,而下面这些值将表明该字段确实存在:空字符串,比如""
或"-"
数组中包含null
和其他值,比如[null, "foo"]
字段映射中的自定义的null-value
注意
查找缺少索引值的文档
要查找缺少字段索引值的文档,请使用 must_not
布尔查询 和 exists
查询。
下面这个搜索返回缺少 user
字段索引值的文档。
GET /_search
{"query": {"bool": {"must_not": {"exists": {"field": "user"}}}}
}
模糊查询 (fuzzy query)
根据莱温斯坦编辑距离,返回包含与搜索词相似的词项的文档。
编辑距离是将一个词转换成另一个词所需的单个字符的变化次数。这些变化包括:
- 改变一个字符 (box → fox)
- 删除一个字符 (black → lack)
- 插入一个字符 (sic → sick)
- 调换两个相邻的字符 (act → cat)
为了找到相似的词,fuzzy
查询在指定的编辑距离内创建搜索词的所有可能变化或扩展的集合。 然后,该查询返回每个扩展的精确匹配。
请求示例
一个简单的例子
GET /_search
{"query": {"fuzzy": {"user": {"value": "ki"}}}
}
一个使用高级参数的例子
GET /_search
{"query": {"fuzzy": {"user": {"value": "ki","fuzziness": "AUTO","max_expansions": 50,"prefix_length": 0,"transpositions": true,"rewrite": "constant_score"}}}
}
fuzzy
的顶级参数
<field>
(必需, object) 你想搜索的字段。
<field>
的参数
value
(必需, string) 你想在指定的<field>
中搜索的词。fuzziness
(可选, string) 匹配允许的最大编辑距离。有效值及更多信息请参考模糊性。max_expansions
(可选, integer) 可创建的最大变形词的数量。 默认为50
。避免在
max_expansions
参数中使用很大的值,尤其是当prefix_length
参数值为0
时。 一个很大的max_expansions
参数值可能会导致性能下降,因为要检查大量的变形词。prefix_length
(可选, integer) 创建扩展时,开头字符保持不变的数量。默认为0
。transpositions
(可选, boolean) 指示编辑是否包括两个相邻字符的换位 (ab → ba)。默认为true
。rewrite
(可选, string) 用于重写查询的方法。 有效值及更多信息请参考rewrite
参数。
注意
如果 search.allow_expensive_queries
设置为false,将不会执行模糊查询。
ids
根据文档的id返回文档。 该查询使用存储在 _id
字段中的文档id。
请求示例
GET /_search
{"query": {"ids" : {"values" : ["1", "4", "100"]}}
}
ids
的顶级参数
values
(必需, 字符串数组) 文档id 数组。
前缀查询 (prefix query)
返回在指定的字段中包含特定前缀的文档。
请求示例
下面这个搜索返回 user
字段包含以 ki
开头的词项的文档。
GET /_search
{"query": {"prefix": {"user": {"value": "ki"}}}
}
prefix
的顶级参数
<field>
(必需, object) 你想要搜索的字段。
<field>
的参数
value
(必需, string) 你希望在指定的<field>
中查找的词项的起始字符。rewrite
(可选, string) 用于重写查询的方法。有效值及更多信息请参考rewrite
参数。
注意
短请求格式的示例
可以通过组合 <field>
和 value
参数来简化 prefix
查询语法。例如:
GET /_search
{"query": {"prefix" : { "user" : "ki" }}
}
提高前缀查询的速度
可以使用 index_prefixes
映射参数来提高前缀查询的速度。 如果启用了该参数,ElasticSearch 会在单独的字段中索引 2 到 5 个字符的前缀。 这让 ElasticSearch 以更大的索引为代价去更有效地运行前缀查询。
允许执行昂贵的查询
如果 search.allow_expensive_queries
设置为false
,则前缀查询不会被执行。 即使有此设置,但是如果启用了 index_prefixes
],则会构建一个优化的查询,该查询不会被认为很慢,因此会被执行。
范围查询 (range query)
返回包含指定范围内的词项的文档。
请求示例
下面这个搜索返回 age
字段包含 10
到 20
之间的词项的文档。
GET /_search
{"query": {"range" : {"age" : {"gte" : 10,"lte" : 20,"boost" : 2.0}}}
}
range
的顶级参数
<field>
(必需, object) 你想搜索的字段。
<field>
的参数
gt
(可选) 大于gte
(可选) 大于等于lt
(可选) 小于lte
(可选) 小于等于format
(可选, string) 用于转换查询中date
值的日期格式。
默认情况下,ElasticSearch 使用<field>
的映射中指定的 dateformat
。 它会覆盖该映射中设置的格式。
有效的语法请参考format
。如果
format
和date
值不完整,ElasticSearch 会用 unix 时间的开始时间(即1970年1月1日)替换任何缺少的年、月或日期部分。例如,如果format
为dd
,则 ElasticSearch 会将gte
值10
转换为1970-01-10T00:00:00.000Z
, 即: 将"gte": "10"
转换为"gte": "1970-01-10T00:00:00.000Z"
。relation
(可选, string) 指示范围查询如何匹配range
字段的值。
有效值有:INTERSECTS
(默认) 匹配范围字段值与查询范围相交的文档。
CONTAINS
匹配范围字段值完全包含查询范围的文档。
WITHIN
匹配范围字段值完全在查询范围内的文档。time_zone
(可选, string) 协调世界时(UTC)时差 或 IANA时区,用于将查询字符串中的date
值转换为 UTC。
有效值包括 ISO 8601 UTC 时差,如+01:00
或-08:00
,以及 IANA 时区识别名称,如America/Los_Angeles
。
有关使用time_zone
参数的查询示例,请参阅范围range
查询中的时区]。time_zone
参数不影响now
的 日期计算值。now
始终是 UTC 中的当前系统时间。 但是,time_zone
参数会对使用now
和 日期计算舍入 计算的日期进行转换。 例如,time_zone
参数会将now/d
的值进行转换。boost
(可选, float) 用于降低或增加查询的相关性评分的浮点数。
默认为1.0
。你可以使用boost
参数来调整包含两个或更多查询的搜索的相关性评分。
boost
值是相对于默认值1.0
的。 其值在0
和1.0
之间时会降低相关性评分,而大于1.0
时会增加相关性评分。
注意
在text
和keyword
类型的字段上使用range
查询
如果 search.allow_expensive_queries
设置为 fasle
,则在 text
或 keyword
类型的字段上的范围查询不会被执行。
在date
类型的字段上使用range
查询
当<field>
参数是一个date
类型的字段时,可以将日期计算与以下参数一起使用:
gt
gte
lt
lte
例如,下面这个搜索返回timestamp
字段包含今天(now)和昨天(now-1d)之间的日期的文档。
GET /_search
{"query": {"range" : {"timestamp" : {"gte" : "now-1d/d","lt" : "now/d"}}}
}
日期计算及舍入
ElasticSearch 对参数中的日期计算的值进行舍入,如下所示:
gt
向上舍入到舍入日期未涵盖的第一个毫秒。例如,2014-11-18||/M
舍入到2014-12-01T00:00:00.000
,不包括整个11月。gte
向下舍入到第一个毫秒。例如,2014-11-18||/M
向下舍入到2014-11-01T00:00:00.000
,包含了整个月。lt
向下舍入到舍入值之前的最后一毫秒。例如,2014-11-18||/M
向下舍入到2014-10-31T23:59:59.999
,不包括整个11月。lte
舍入到舍入间隔中最近的一毫秒。例如,2014-11-18||/M
向上舍入到2014-11-30T23:59:59.999
,包含整个月。
使用time_zone
参数的查询示例
可以使用 time_zone
参数通过 UTC 时差将 date
值转换为UTC。例如:
GET /_search
{"query": {"range": {"timestamp": {"time_zone": "+01:00", "gte": "2020-01-01T00:00:00", "lte": "now" }}}
}
- 指示
date
值使用+01:00
的UTC时差。 - 使用 UTC 时差
+01:00
,ElasticSearch 将此日期转换为2019-12-31T23:00:00 UTC
。 - 参数
time_zone
不会影响now
的值。
正则表达式查询 (regexp query)
返回包含匹配正则表达式的词项的文档。
正则表达式是一种使用占位符(称为运算符)来匹配数据模式的方法。 有关regexp
查询支持的运算符列表,请参见正则表达式语法。
请求示例
下面这个搜索返回user
字段包含任何以k
开头并以y
结尾的词项的文档。 运算符.*
匹配任何长度的任何字符,包括0个字符。 匹配的词项可以包含 ky
、kay
和 kimchy
。
GET /_search
{"query": {"regexp": {"user": {"value": "k.*y","flags" : "ALL","max_determinized_states": 10000,"rewrite": "constant_score"}}}
}
regexp
的顶级参数
<field>
(必需, object) 你想搜索的字段。
<field>
的参数
value
(必需, string) 要在指定的<field>
中查找的词项的正则表达式。 支持的运算符列表,请参考正则表达式语法。
默认情况下,正则表达式限制为1000个字符。 可以使用index.max_regex_length
设置来更改此限制。regexp
查询的性能会因给定的正则表达式而不同。 要提高查询性能,应避免使用通配符模式,如.*
或者.*?+
,没有前缀或后缀。flags
(可选, string) 为正则表达式启用可选的运算符。有效值及更多信息请参考正则表达式语法。max_determinized_states
(可选, integer) 查询所需的最大自动机状态数。 默认为10000
。
ElasticSearch 在内部使用 Apache Lucene 解析正则表达式。 Lucene 将每个正则表达式转换成一个包含许多确定状态的有限自动机。
你可以使用此参数来防止该转换无意中消耗太多资源。 你可能需要增加这个限制来运行复杂的正则表达式。rewrite
(可选, string) 用于重写查询的方法。有效值及更多信息请参考rewrite
参数。
注意
允许执行昂贵的查询
如果 search.allow_expensive_queries
设置为 false
, 则正则查询不会被执行。
term 查询
返回指定的字段中包含确切的词项的文档。
可以使用 term
查询根据精确的值(如价格、产品ID或用户名)来查找文档。
避免对 text
字段使用 term
查询。
默认情况下,作为分析(analysis)的一部分,ElasticSearch 会更改 text
字段的值。 这使得查找 text
字段值的精确匹配变得困难。
要搜索 text
字段的值,请使用 match
查询代替之。
请求示例
GET /_search
{"query": {"term": {"user": {"value": "Kimchy","boost": 1.0}}}
}
term
的顶级参数
<field>
(必需, object) 你想搜索的字段。
<field>
的参数
value
(必需, string) 希望在指定的<field>
中查找的词项。 要返回文档,词项必须与字段值完全匹配,包括空格和大写。boost
(可选, float) 用于降低或增加查询的相关性评分的浮点数。默认为1.0
。
你可以使用boost
参数来调整包含两个或更多查询的搜索的相关性评分。
boost
值是相对于默认值1.0
的。 其值在0
和1.0
之间时会降低相关性评分,而大于1.0
时会增加相关性评分。
注意
避免在text
字段上使用term
查询
默认情况下,ElasticSearch 会在分析过程中更改text
字段的值。 例如,默认的 standard 分析器 按如下方式更改text
字段的值:
- 删除大部分标点符号
- 将剩余的内容分成单独的单词,称为 token(词元)
- 把词元(token)转小写
为了更好地搜索text
字段,match
查询还会在执行搜索之前分析你提供的搜索词。 这意味着match
查询可以在text
字段中搜索已分析的词元(token),而不是确切的词项。
term
查询不分析要搜索的词。term
查询仅搜索你提供的确切的词。 这意味着在搜索text
字段时,term
查询可能返回很差的结果或没有结果。
要查看搜索结果的差异,请尝试以下示例。
- 创建一个索引,其含有一个名为
full_text
的text
类型的字段。
PUT my_index
{"mappings" : {"properties" : {"full_text" : { "type" : "text" }}}
}
- 添加并索引一个文档,其
full_text
字段的值为Quick Brown Foxes!
PUT my_index/_doc/1
{"full_text": "Quick Brown Foxes!"
}
因为 full_text
是一个 text
类型的字段,ElasticSearch 在分析过程中将 Quick Brown Foxes!
变成了 [quick, brown, fox]
。
3. 使用 term
查询在字段 full_text
中搜素 Quick Brown Foxes!
。 包括pretty
参数,这样响应更具可读性。
GET my_index/_search?pretty
{"query": {"term": {"full_text": "Quick Brown Foxes!"}}
}
因为字段 full_text
不再包含 确切的 词 Quick Brown Foxes!
,因此 term
查询返回结果为空。
4. 使用 match
查询在字段 full_text
中搜素 Quick Brown Foxes!
。
GET my_index/_search?pretty
{"query": {"match": {"full_text": "Quick Brown Foxes!"}}
}
与 term
查询不同,match
查询在执行搜索前,对给定的搜索词 Quick Brown Foxes!
进行了分析。 然后 match
查询返回任何 full_text
字段中包含了quick
、brown
或 fox
词元的文档。
下面是对结果中包含索引文档的 match
查询的响应:
{"took" : 1,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 0.8630463,"hits" : [{"_index" : "my_index","_type" : "_doc","_id" : "1","_score" : 0.8630463,"_source" : {"full_text" : "Quick Brown Foxes!"}}]}
}
terms 查询
返回指定的字段中包含一个或多个确切的词的文档。
除了可以搜索多个值,terms
查询和 term
查询一样。
请求示例
下面这个搜索返回 user
字段包含kimchy
或ElasticSearch
的文档。
GET /_search
{"query" : {"terms" : {"user" : ["kimchy", "ElasticSearch"],"boost" : 1.0}}
}
terms
的顶级参数
<field>
(可选, object) 你想搜索的字段。
该参数的值是你想在指定的字段中查找的一组词。 要返回文档,一个或多个词必须与字段值精确匹配,包括空格和大写。
默认情况下,ElasticSearch 将terms
查询限制为最多 65,536 个词。 可以使用index.max_terms_count
设置来更改此限制。要将现有文档的字段的值用作搜索词,请使用词项查找(terms lookup)参数。
boost
(可选, float) 用于降低或增加查询的相关性评分的浮点数。默认为1.0
。
你可以使用boost
参数来调整包含两个或更多查询的搜索的相关性评分。
boost
值是相对于默认值1.0
的。 其值在0
和1.0
之间时会降低相关性评分,而大于1.0
时会增加相关性评分。
注意
高亮 terms
查询
高亮 只是尽力而为。 ElasticSearch 可能不会返回terms
查询的高亮结果,具体取决于:
- 高亮器(highlighter)的类型
- 查询中词的数量
词项查找(terms lookup)
词项查找获取现有文档的字段值。 然后,ElasticSearch 使用这些值作为搜索词。 这在搜索大量词项时会很有帮助。
因为词项查找从文档中获取值,所以必须启用 _source
映射字段才能使用词项查找。 _source
字段默认是启用的。
默认情况下,ElasticSearch 将
terms
查询限制为最多 65,536 个词。 这包括了使用词项查找获取的词项。 可以使用index.max_terms_count
设置来更改此限制。
若要执行词项查找,请使用以下参数。
词项查找(terms lookup)的参数
index
(必需, string) 要从中提取字段值的索引的名称。id
(必需, string) 要获取字段值的文档的 ID。path
(必需, string) 要从中提取字段值的字段的名称。 ElasticSearch 使用这些字段的值作为查询的搜索词。如果字段值包含嵌套内部对象的数组,则可以使用点标记语法来访问这些对象。routing
(可选, string) 要从中提取词项值的文档的自定义的 路由值。 如果在为文档编制索引时提供了自定义的路由值,则此参数是必需的。
词项查找(terms lookup)示例
要了解词项查找的工作原理,请尝试以下示例。
- 创建一个索引,其有一个名为
color
、类型为keyword
的字段。
PUT my_index
{"mappings" : {"properties" : {"color" : { "type" : "keyword" }}}
}
- 添加并索引一个文档,其 id 为 1,字段
color
的值为["blue", "green"]
。
PUT my_index/_doc/1
{"color": ["blue", "green"]
}
- 添加并索引另一个文档,其 id 为 2,字段
color
的值为blue
。
PUT my_index/_doc/2
{"color": "blue"
}
- 使用带词项查找参数的
terms
查询去查找包含与文档 2 中的一个或多个词项相同的文档。 包括pretty
参数,这样响应更具可读性。
GET my_index/_search?pretty
{"query": {"terms": {"color" : {"index" : "my_index","id" : "2","path" : "color"}}}
}
因为文档 2 和文档 1 在color
字段中都包含blue
,所以 ElasticSearch 返回了这两个文档。
{"took" : 17,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "my_index","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"color" : ["blue","green"]}},{"_index" : "my_index","_type" : "_doc","_id" : "2","_score" : 1.0,"_source" : {"color" : "blue"}}]}
}
terms_set 查询
返回在指定字段中包含最少数量的确切的词项的文档。
除了可以定义返回文档必需匹配的词项的数量,terms_set
查询和 terms
查询是一样的。例如:
- 一个
programming_languages
字段,包含求职者的已知编程语言的列表,比如c++
、java
或php
。 可以使用terms_set
查询返回至少匹配其中两种语言的文档。 - 一个
permissions
字段,包含应用程序的可能的用户权限列表。 可以使用terms_set
查询返回与这些权限的子集相匹配的文档。
请求示例
创建索引
要使用terms_set
查询,在大多数情况下,需要在索引中包含一个 numeric 字段映射。 这个 numeric 字段包含返回文档所需的匹配项的数量。
要了解如何为terms_set
查询设置索引,请尝试以下示例。
- 创建一个索引
job-candidates
(求职者),其字段映射如下:name
,一个keyword
类型的字段。 此字段包含求职者的姓名。programming_languages
,一个keyword
类型的字段。 此字段包含求职者已知的编程语言。required_matches
,一个 numericlong
类型的字段。 此字段包含返回文档所需的匹配项的数量。
PUT /job-candidates
{"mappings": {"properties": {"name": {"type": "keyword"},"programming_languages": {"type": "keyword"},"required_matches": {"type": "long"}}}
}
- 添加并索引一个id为
1
的文档,字段值如下:name
:Jane Smith
programming_languages
:["c++", "java"]
。required_matches
:2
包含?refresh
参数,以便可以立即搜索文档。
PUT /job-candidates/_doc/1?refresh
{"name": "Jane Smith","programming_languages": ["c++", "java"],"required_matches": 2
}
- 添加并索引另一个id为
2
的文档,字段值如下:name
:Jason Response
programming_languages
:["java", "php"]
required_matches
:2
PUT /job-candidates/_doc/2?refresh
{"name": "Jason Response","programming_languages": ["java", "php"],"required_matches": 2
}
现在,你可以使用required_matches
字段的值作为在terms_set
查询中返回文档所需的匹配的词项数。
查询示例
下面这个搜索返回 programming_languages
字段包含至少两个以下词项的文档:
c++
java
php
minimum_should_match_field
的值为required_matches
。 这意味着所需的匹配项的数量是2
,即required_matches
字段的值。
GET /job-candidates/_search
{"query": {"terms_set": {"programming_languages": {"terms": ["c++", "java", "php"],"minimum_should_match_field": "required_matches"}}}
}
terms_set
的顶级参数
<field>
(必需, object) 你想搜索的字段。
<field>
的参数
terms
(必需, array of strings) 你想在指定的<field>
中搜索的词的数组。 要返回一个文档,所需数量的词项必须与字段值完全匹配,包括空格和大写。
所需的匹配词项的数量在参数minimum_should_match_field
或minimum_should_match_script
中定义。minimum_should_match_field
(可选, string) 包含返回文档所需的匹配词项数量的 numeric 字段。minimum_should_match_script
(可选, string) 包含返回文档所需的匹配词项数量的自定义脚本。
参数及有效值请参考脚本。
有关使用minimum_should_match_script
参数的例子,请参考本节后面的如何使用minimum_should_match_script
参数?。
注意
如何使用minimum_should_match_script
参数?
可以通过 minimum_should_match_script
来使用脚本去定义所需的匹配词项的数量。 如果你需要动态设置所需词项的数量,这将非常有用。
使用minimum_should_match_script
的查询示例
下面这个搜索返回programming_languages
字段包含至少两个以下词项的文档:
c++
java
php
该查询中的参数source
表明:- 需要匹配的词项数量不能超过
params.num_terms
,即terms
字段中提供的词项数。 - 需要匹配的词项数量是
2
,即required_matches
字段的值。
GET /job-candidates/_search
{"query": {"terms_set": {"programming_languages": {"terms": ["c++", "java", "php"],"minimum_should_match_script": {"source": "Math.min(params.num_terms, doc['required_matches'].value)"},"boost": 1.0}}}
}
通配符查询(wildcard query)
返回包含匹配通配符模式的词项的文档。
通配符运算符是匹配一个或多个字符的占位符。 例如,*
通配符运算符匹配零个或多个字符。 可以将通配符运算符与其他字符组合起来创建通配符模式。
请求示例
下面这个搜索返回user
字段包含以 ki
开头并以 y
结尾的词的文档。 这些匹配的词项可以包括kiy
、kity
或 kimchy
。
GET /_search
{"query": {"wildcard": {"user": {"value": "ki*y","boost": 1.0,"rewrite": "constant_score"}}}
}
wildcard
的顶级参数
<field>
(必需, object) 你想要搜索的字段。
<field>
的参数
value
(必需, string) 你想在指定的<field>
中查找的词项的通配符模式。
此参数支持两个通配符运算符:?
,它匹配任何单个字符*
,,可以匹配零个或多个字符,包括一个空字符避免模式以*
或?
开头。
这可能会增加查找匹配项所需的迭代次数,并降低搜索性能。
boost
(可选, float) 用于降低或增加查询的相关性评分的浮点数。默认为1.0
。你可以使用boost
参数来调整包含两个或更多查询的搜索的相关性评分。boost
值是相对于默认值1.0
的。 其值在0
和1.0
之间时会降低相关性评分,而大于1.0
时会增加相关性评分。rewrite
(可选, string) 用于重写查询的方法。有效值及更多信息请参考rewrite
参数。
注意
允许昂贵的查询
如果search.allow_expensive_queries
设置为false
,则通配符查询不会被执行。
minimum_should_match
参数
参数 minimum_should_match
的可能的值如下:
类型 | 示例 | 描述 |
---|---|---|
整数 | 3 |
表示一个固定值,与可选子句的数量无关。 |
负整数 | -2 |
表示可选子句的总数,减去这个数目应该是强制性的。 |
百分比 | 75% |
表示可选子句总数的这个百分比是必需的。根据百分比计算出的数字被向下舍入并用作最小值。 |
负百分比 | -25% |
表示可选子句总数的这个百分比可以缺失。 从百分比中计算出的数字向下四舍五入,然后从总数中减去以确定最小值。 |
组合 | 3<90% |
一个正整数,后面跟小于号,再跟前面提到的任意一个说明符,这是一个条件规范。 它表示:如果可选子句的数量等于(或小于)整数,则它们都是必需的;但是如果可选子句的数量大于整数,则此规范适用。 在这个例子中:如果有 1 ~ 3 个子句,它们都是必需的,但是对于4个或更多个子句,只有90%是必需的。 |
多个组合 | 2<-25% 9<-3 |
多个条件规范可以用空格分隔,每个条件规范只对大于它前面的数字有效。 在这个例子中:如果有 1 ~ 2 个条款,两者都是必需的;如果有 3 ~ 9 个条款,除了 25% 都是必需的;如果有 9 个以上的条款,除了 3 都是必需的。 |
注意:
在处理百分比时,负值可用于在边缘(edge)情况下获得不同的行为。 在处理 4 个子句时,75% 和 -25% 的意思是一样的,但在处理 5 个子句时,75% 表示需要3个子句,而 -25% 表示需要 4 个子句。
如果基于规范的计算确定不需要可选子句,那么关于 bool 查询的常规规则在搜索时仍然适用(不包含必需子句的 bool 查询仍然必须匹配至少一个可选子句)
无论计算结果是多少,都不会使用大于可选子句数的值或小于1的值。 (即:无论计算结果的结果有多低或多高,要求的最小匹配数永远不会低于1或大于子句数。)
rewrite
参数
此参数仅供专业用户使用,更改此参数的值会影响搜索性能和相关性。
ElasticSearch 在内部使用 Apache Lucene 来支持索引和搜索。 在它们原始的形式中,Lucene 不能执行以下查询:
fuzzy
prefix
query_string
regexp
wildcard
为了执行它们,Lucene 将这些查询转换成更简单的形式,比如bool
查询或位组(bit set)。
参数rewrite
决定了:- Lucene 如何计算每个匹配文档的相关性分数
- Lucene 是否将原始查询更改为
bool
查询或位组(bit set) - 如果更改为
bool
查询,将包括哪些term
查询子句
有效值
constant_score
(默认)
对较少的匹配词项使用constant_score_boolean
方法。 否则,该方法将按顺序查找所有匹配的词项,并使用一个位组(bit set)返回匹配的文档。constant_score_boolean
为每个文档分配一个与boost
参数相等的相关性分数。该方法将原始查询更改为bool
查询。 这个bool
查询包含一个should
子句和针对每个匹配词项的term
查询。此方法会导致最终的bool
查询超过indices.query.bool.max_clause_count
设置中的子句的数量限制。 如果查询超过这个限制,ElasticSearch 将返回一个错误。scoring_boolean
计算每个匹配文档的相关性分数。该方法将原始查询更改为bool
查询。 这个bool
查询包含一个should
子句和针对每个匹配词项的term
查询。此方法会导致最终的bool
查询超过indices.query.bool.max_clause_count
设置中的子句的数量限制。 如果查询超过这个限制,ElasticSearch 将返回一个错误。top_terms_blended_freqs_N
计算每个匹配文档的相关性分数,就好像所有词项具有相同的频率一样。 这个频率是所有匹配词项的最大频率。该方法将原始查询更改为bool
查询。 这个bool
查询包含一个should
子句和针对每个匹配词项的term
查询。最终的bool
查询仅包括对前N
个得分的词项的term
查询。可以使用此方法避免超出indices.query.bool.max_clause_count
设置中的子句的数量限制。top_terms_boost_N
为每个匹配文档分配一个与boost
参数相等的相关性分数。该方法将原始查询更改为bool
查询。 这个bool
查询包含一个should
子句和针对每个匹配词项的term
查询。最终的bool
查询仅包括对前N
个得分的词项的term
查询。可以使用此方法避免超出indices.query.bool.max_clause_count
设置中的子句的数量限制。top_terms_N
计算每个匹配文档的相关性分数。该方法将原始查询更改为bool
查询。 这个bool
查询包含一个should
子句和针对每个匹配词项的term
查询。最终的bool
查询仅包括对前N
个得分的词项的term
查询。可以使用此方法避免超出indices.query.bool.max_clause_count
设置中的子句的数量限制。
rewrite
参数的性能考量
对于大多数使用场景,建议使用 constant_score
、constant_score_boolean
或 top_terms_boost_N
重写方法。
其他方法都要计算相关性分数。这些分数的计算通常开销很大,并且不会改善查询结果。
正则表达式语法
正则表达式是一种使用占位符(称为运算符)来匹配数据模式的方法。
ElasticSearch 支持在以下查询中使用正则表达式:
regexp
query_string
ElasticSearch 使用 Apache Lucene 的正则表达式引擎来解析这些查询。
保留字符
Lucene 的正则表达式引擎支持所有 Unicode 字符。但是,以下字符被保留作为运算符:
. ? + * | { } [ ] ( ) " \
根据所启用的 可选运算符,以下字符也会被保留:
@ & < > ~
要按字面意思使用其中一个字符,请在前面加一个反斜杠对其进行转义,或者用双引号将其括起来。例如:
@ # renders as a literal '@'
\ # renders as a literal ''
"john@smith.com" # renders as 'john@smith.com'
标准运算符
Lucene 的正则表达式引擎不使用 Perl兼容的正则表达式(PCRE) 库,但是它支持以下标准运算符。
-
.
匹配任何字符。例如:ab. # 匹配 'aba'、'abb'、'abz' 等
-
?
重复前面的字符零次或一次。通常用于使前面的字符可选。例如:abc? # 匹配 'ab' 和 'abc'
-
+
重复前面的字符一次或多次。例如:ab+ # 匹配 'ab'、'abb'、'abbb' 等
-
\*
重复前面的字符零次或多次。例如:ab* # 匹配 'a'、'ab'、'abb'、'abbb' 等
-
{}
前面的字符可以重复的最小和最大次数。例如:a{2} # 匹配 'aa' a{2,4} # 匹配 'aa'、'aaa' 和 'aaaa' a{2,} # 匹配 'a' 重复2次或更多次
-
|
或(OR) 运算符。如果左侧或右侧的最长模式匹配,则匹配成功。例如:abc|xyz # 匹配 'abc' 和 'xyz'
-
( … )
形成一个分组。可以使用分组将表达式的一部分视为单个字符。例如:abc(def)? # 匹配 'abc' 和 'abcdef',但不匹配 'abcd'
-
[ … ]
匹配括号中的一个字符。例如:[abc] # 匹配 'a', 'b', 'c'
在括号内,
-
表示一个范围,除非-
是第一个字符或被转义了。例如:
[a-c] # 匹配 'a'、'b' 或 'c'
[-abc] # '-' 是第一个字符,匹配 '-'、'a'、'b' 或 'c'
[abc\-] # 转义'-',匹配 'a'、'b'、'c' 或 '-'
方括号中字符前的 ^
否定该字符或范围。例如:
[^abc] # 匹配除了 'a'、'b'、'c' 的任意字符
[^a-c] # 匹配除了 'a'、'b'、'c' 的任意字符
[^-abc] # 匹配除了 '-'、'a'、'b'、'c' 的任意字符
[^abc\-] # 匹配除了 'a'、'b'、'c'、'-' 的任意字符
可选的运算符
可以使用 flags
参数为 Lucene 的正则表达式引擎启用更多可选的运算符。
要启用多个运算符,请使用 |
分隔符。 例如,flags
值为COMPLEMENT|INTERVAL
表示启用 COMPLEMENT
和 INTERVAL
运算符。
有效值
ALL
(默认)
启用所有可选的运算符。COMPLEMENT
启用~
运算符。 可以用~
来否定最短的跟随模式。例如:a~bc # 匹配 'adc' 和 'aec',但不匹配 'abc'
INTERVAL
启用<>
运算符。 可以使用<>
来匹配数值范围。例如:foo<1-100> # 匹配 'foo1', 'foo2' ... 'foo99', 'foo100' foo<01-100> # 匹配 'foo01', 'foo02' ... 'foo99', 'foo100'
INTERSECTION
启用&
运算符,它充当 与(AND) 运算符。 如果左侧和右侧的模式都匹配,则匹配成功。例如:aaa.+&.+bbb # 匹配 'aaabbb'
ANYSTRING
启用@
运算符。 可以使用@
来匹配任何完整的字符串。可以将@
运算符与&
和~
运算符结合起来创建一个“除此之外的一切”逻辑。例如:@&~(abc.+) # 匹配除了 'abc' 开头的一切
不支持的运算符
Lucene 的正则表达式引擎不支持定位符,比如 ^
(行首)或 $
(行尾)。 要匹配某个词项,正则表达式必须匹配整个字符串。
专业的查询 (Specialized queries)
该组包含的是不适合其他组的查询:
distance_feature
(距离特性)查询
一种根据动态计算的原点(origin)与文档的 date、date_nanos 和 geo_point 字段之间的距离来计算分数的查询。 它能够有效地跳过非竞争性的(non-competitive)命中。 (基于时间或坐标的查询,越接近原点得分越高)more_like_this
(更相似)查询
该查询查找与指定文本、文档或文档集合相似的文档。percolate
查询
该查询查找存储为与指定文档匹配的文档的查询。rank_feature
查询
一种基于数字特征的值计算分数的查询,能够有效地跳过非竞争性的(non-competitive)命中。script
查询
该查询允许使用一个脚本充当过滤器。 另请参考function_score
查询。script_score
(脚本评分)查询
一种允许使用脚本修改子查询分数的查询。wrapper
(脚本)查询
接受其他查询作为 json 或 yaml 字符串的查询。pinned
(置顶的)查询
将所选文档提升到与给定查询匹配的其他文档之上的查询。 (提升特定文档的查询)
geo(地理位置查询)
ElasticSearch 支持两种 geo 数据类型:支持纬度(lat)/经度(lon)的字段geo_point
,以及支持点(points)、线(lines)、圆(circles)、多边形(polygons), 多个多边形(multi-polygons)等的字段 geo_shape
。
该组中的查询包括:
geo_bounding_box
查询
查找 geo-points 落在指定矩形内的文档。geo_distance
查询
查找 geo-points 在中心点指定距离内的文档。geo_polygon
查询
查找 geo-points 在指定的多边形内的文档。geo_shape
查询
查找有以下类型的文档:geo-shapes
: 与指定的地理形状相交、被包含或不相交geo-points
: 与指定的地理形状相交
形状查询
与geo_shape
一样,ElasticSearch 支持对任意二维(非地理空间)几何图形进行索引,从而可以绘制出虚拟世界、体育场馆、主题公园和 CAD 图。 shape
字段类型支持点(point)、线(line)、多边形(polygon)、多重多边形( multi-polygon)、包络线(envelope)等。
该组中的查询有:
shape
查询
查找形状与指定形状相交、位于指定形状内或不相交的文档。