multi_match查询建立在match query的基础上,允许多字段查询:
GET /_search
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
可以使用通配符指定字段,例如:
GET /_search
{
"query": {
"multi_match" : {
"query": "Will Smith",
"fields": [ "title", "*_name" ]
}
}
}
单个字段可以通过插入符号(^)来增强:
GET /_search
{
"query": {
"multi_match" : {
"query" : "this is a test",
"fields" : [ "subject^3", "message" ]
}
}
}
该查询将subject字段的分数乘以3,但保持message字段的分数不变。
如果没有提供字段,multi_match查询默认为index.query.default_field索引设置,而后者默认为*。*提取映射中符合术语查询条件的所有字段,并过滤元数据字段。然后将所有提取的字段组合起来构建一个查询。
multi_match查询在内部执行的方式取决于type参数,可以将其设置为:
| (默认) 查找与任何字段匹配的文档,但使用 |
| 查找与任何字段匹配的文档并组合来自每个字段的 |
| 像对待 |
| 对每个字段运行 |
| 对每个字段运行 |
| 在每个字段上创建一个 |
best_fields类型在搜索多个在同一字段中最容易找到的单词时最有用。例如,单个字段中的“brown fox”要比一个字段中的“brown”和另一个字段中的“fox”更有意义。
best_fields类型为每个字段生成一个匹配查询,并将它们包装在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、fuzzy_rewrite、zero_terms_query、cutoff_frequency、auto_generate_synonyms_phrase_query和fuzzy_transposition,如匹配查询中解释的。
most_fields
当查询包含以不同方式分析的相同文本的多个字段时,该类型最有用。例如,主字段可能包含同义词、词干和没有变音符号的术语。第二个字段可能包含原始术语,第三个字段可能包含带状疱疹。通过结合所有三个字段的分数,我们可以将尽可能多的文档与主字段匹配,但使用第二个和第三个字段将最相似的结果推送到列表顶部。
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、fuzzy_rewrite、zero_terms_query和cutoff_frequency,如匹配查询中解释的,但请参见operator和minimum_should_match。
phrase和phrase_prefix类型的行为类似于best_fields,但它们使用match_phrase或match_phrase_prefix查询而不是匹配查询。
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" }}
]
}
}
}
此外,接受analyzer、boost、lenient和zero_terms_query,如Match中解释的,以及slop,在Match短语中解释。类型phrase_prefix另外接受max_expansions。
该cross_fields
类型与结构化文档在多个领域特别有用应该相匹配。例如,当查询first_name
和last_name
字段中的“Will Smith”时,最佳匹配很可能在一个字段中包含“Will”而在另一个字段中包含“Smith”。
这听起来像是most_fields的工作,但这种方法有两个问题。第一个问题是,operater和minimum_should_match是针对每个字段应用的,而不是针对每个term(参见上面的解释)。
第二个问题与相关性有关:first_name和last_name字段中的不同术语频率可能会产生意想不到的结果。
例如,假设我们有两个人:“Will Smith” 和 “Smith Jones”。“Smith”作为姓很常见(所以不太重要),但“Smith”作为名很不常见(所以很重要)。
如果我们搜索“Will Smith”,“Smith Jones”文档可能会出现在更匹配的“Will Smith”上面,因为first_name: Smith的得分超过了first_name: Will加last_name: Smith的得分之和。
处理这些类型的查询的一种方法是简单地将first_name
和last_name
字段索引 到单个full_name
字段中。当然,这只能在索引时完成。
该cross_field
类型试图通过采用以术语为中心的方法在查询时解决这些问题 。它首先将查询字符串分析为单独的术语,然后在任何字段中查找每个术语,就好像它们是一个大字段一样。
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进行比较 。)
这解决了两个问题之一。不同词频的问题是通过混合所有领域的词频来解决的,以消除差异。
在实践中,first_name:smith
将被视为与 last_name:smith
具有相同的频率,加一。这将使匹配 first_name
并last_name
具有可比的分数,last_name
因为它是最有可能包含smith
.
注意,cross_fields通常只对boost为1的短字符串字段有用。除此之外,术语频率和长度标准化也会对分数产生影响,从而导致术语统计数据的混合不再有意义。
如果你通过Validate运行上面的查询,它会返回如下解释:
+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,如匹配查询中解释的那样。
cross_field类型只能在具有相同分析器的字段上以术语为中心模式工作。与上面的示例一样,使用同一个分析器的字段被分组在一起。如果有多个组,查询将使用任何组中的最佳分数。
例如,如果我们有一个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
andlast
将被组合在一起并被视为单个字段,并且first.edge
和last.edge
将被组合在一起并被视为单个字段。
拥有多个组很好,但是当与operator或minimum_should_match组合时,它可能会遇到与most_fields或best_fields相同的问题。
您可以很容易地自己将这个查询重写为两个独立的cross_fields查询结合dis_max查询,并仅对其中一个应用minimum_should_match参数:
GET /_search
{
"query": {
"dis_max": {
"queries": [
{
"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" ]
}
}
]
}
}
}
通过在查询中指定analyzer参数,可以将所有字段强制放入同一组。
GET /_search
{
"query": {
"multi_match" : {
"query": "Jon",
"type": "cross_fields",
"analyzer": "standard",
"fields": [ "first", "last", "*.edge" ]
}
}
}
执行方式如下:
blended("will", fields: [first, first.edge, last.edge, last])
blended("smith", fields: [first, first.edge, last.edge, last])
默认情况下,每个词混合查询将使用组中任何字段返回的最佳分数。然后,在组合不同组的分数时,查询使用任何组的最佳分数。tie_breaker参数可以改变这两个步骤的行为:
| 从(例如) |
| 将 (eg) |
| 取单个最佳分数加上 |
该bool_prefix
类型的评分行为类似于most_fields,但使用 match_bool_prefix查询而不是 match
查询。
GET /_search
{
"query": {
"multi_match" : {
"query": "quick brown f",
"type": "bool_prefix",
"fields": [ "subject", "message" ]
}
}
}
支持匹配查询中解释的analyzer、boost、operator、minimum_should_match、lenient、zero_terms_query和auto_generate_synonyms_phrase_query参数。用于构造词汇查询的词汇支持fuzzy、prefix_length、max_expansions、fuzzy_rewrite和fuzzy_transpositions参数,但对从最后一个词汇构造的前缀查询没有影响。
这种查询类型不支持slop和cutoff_frequency参数。