专用查询

edit

此组包含不适合归入其他组的查询:

distance_feature query
一个根据原点与文档的 datedate_nanosgeo_point 字段之间的动态计算距离来计算分数的查询。 它能够有效地跳过非竞争性的命中。
more_like_this query
此查询查找与指定文本、文档或文档集合相似的文档。
percolate query
此查询查找存储为与指定文档匹配的文档的查询。
rank_feature query
一个根据数值特征的值计算分数的查询,并且能够高效地跳过非竞争性的结果。
script query
此查询允许脚本充当过滤器。另请参见 function_score 查询
script_score query
一个允许使用脚本修改子查询得分的查询。
wrapper query
一个接受其他查询作为json或yaml字符串的查询。
pinned query
一种在给定查询中将选定文档优先于其他匹配文档的查询。
rule query
支持将基于查询的上下文规则(使用查询规则API定义)应用于给定查询的查询。

距离特征查询

edit

提升接近提供的原点日期或点的文档的相关性分数。例如,您可以使用此查询来给予更接近某个日期或位置的文档更多权重。

您可以使用 distance_feature 查询来查找与某个位置最近的邻居。您还可以在 bool 搜索的 should 过滤器中使用该查询,以向 bool 查询的分数添加提升的相关性分数。

示例请求

edit

索引设置

edit

要使用 distance_feature 查询,您的索引必须包含一个 datedate_nanosgeo_point 字段。

要查看如何为 distance_feature 查询设置索引,请尝试以下示例。

  1. 创建一个包含以下字段映射的 items 索引:

    PUT /items
    {
      "mappings": {
        "properties": {
          "name": {
            "type": "keyword"
          },
          "production_date": {
            "type": "date"
          },
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
  2. 将多个文档索引到此索引中。

    PUT /items/_doc/1?refresh
    {
      "name" : "chocolate",
      "production_date": "2018-02-01",
      "location": [-71.34, 41.12]
    }
    
    PUT /items/_doc/2?refresh
    {
      "name" : "chocolate",
      "production_date": "2018-01-01",
      "location": [-71.3, 41.15]
    }
    
    
    PUT /items/_doc/3?refresh
    {
      "name" : "chocolate",
      "production_date": "2017-12-01",
      "location": [-71.3, 41.12]
    }

示例查询

edit
基于日期提升文档
edit

以下 bool 搜索返回 name 值为 chocolate 的文档。该搜索还使用 distance_feature 查询来增加 production_date 值更接近 now 的文档的相关性分数。

GET /items/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "name": "chocolate"
        }
      },
      "should": {
        "distance_feature": {
          "field": "production_date",
          "pivot": "7d",
          "origin": "now"
        }
      }
    }
  }
}
基于位置提升文档
edit

以下 bool 搜索返回 name 值为 chocolate 的文档。该搜索还使用 distance_feature 查询来增加 location 值更接近 [-71.3, 41.15] 的文档的相关性分数。

GET /items/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "name": "chocolate"
        }
      },
      "should": {
        "distance_feature": {
          "field": "location",
          "pivot": "1000m",
          "origin": [-71.3, 41.15]
        }
      }
    }
  }
}

用于distance_feature的顶级参数

edit
field

(必需,字符串)用于计算距离的字段名称。此字段必须满足以下条件:

origin

(必需,字符串) 用于计算距离的日期或起始点。

如果 field 值是 datedate_nanos 字段,则 origin 值必须是 日期。 支持 日期数学,例如 now-1h

如果 field 的值是一个 geo_point 字段,那么 origin 的值必须是一个地理点。

pivot

(必需,时间单位距离单位) 距离 origin 的距离,在此距离处相关性得分将获得 boost 值的一半。

如果 field 的值是 datedate_nanos 字段,pivot 的值必须是 时间单位,例如 1h10d

如果 field 值是一个 geo_point 字段,pivot 值必须是 距离单位,例如 1km12m

boost

(可选, 浮点数) 用于乘以匹配文档的相关性分数的浮点数。此值不能为负数。默认为 1.0

注释

edit

如何计算distance_feature查询的相关性分数

edit

The distance_feature query 动态计算 origin 值与文档字段值之间的距离。然后使用此距离作为特征来提升更接近文档的 相关性分数

The distance_feature query 计算文档的 相关性分数 如下:

relevance score = boost * pivot / (pivot + distance)

The distanceorigin 值与文档字段值之间的绝对差值。

跳过非竞争性命中

edit

function_score查询或其他改变相关性分数的方式不同,distance_feature查询在track_total_hits参数不是true时,能够高效地跳过非竞争性的命中结果。

更多类似此查询

edit

More Like This 查询用于查找与给定文档集“相似”的文档。为此,MLT 会选择这些输入文档的一组代表性术语,使用这些术语形成查询,执行查询并返回结果。用户可以控制输入文档、术语的选择方式以及查询的形成方式。

最简单的用例包括请求与提供的文本片段相似的文档。在这里,我们请求所有在其“标题”和“描述”字段中包含与“很久以前”相似文本的电影,并将选定的条目数量限制为12个。

GET /_search
{
  "query": {
    "more_like_this" : {
      "fields" : ["title", "description"],
      "like" : "Once upon a time",
      "min_term_freq" : 1,
      "max_query_terms" : 12
    }
  }
}

一个更复杂的用例包括将文本与索引中已存在的文档混合。在这种情况下,指定文档的语法与Multi GET API中使用的语法类似。

GET /_search
{
  "query": {
    "more_like_this": {
      "fields": [ "title", "description" ],
      "like": [
        {
          "_index": "imdb",
          "_id": "1"
        },
        {
          "_index": "imdb",
          "_id": "2"
        },
        "and potentially some more text here as well"
      ],
      "min_term_freq": 1,
      "max_query_terms": 12
    }
  }
}

最后,用户可以混合一些文本、一组选定的文档,还可以提供不一定存在于索引中的文档。要提供不存在于索引中的文档,语法类似于人工文档

GET /_search
{
  "query": {
    "more_like_this": {
      "fields": [ "name.first", "name.last" ],
      "like": [
        {
          "_index": "marvel",
          "doc": {
            "name": {
              "first": "Ben",
              "last": "Grimm"
            },
            "_doc": "You got no idea what I'd... what I'd give to be invisible."
          }
        },
        {
          "_index": "marvel",
          "_id": "2"
        }
      ],
      "min_term_freq": 1,
      "max_query_terms": 12
    }
  }
}

工作原理

edit

假设我们想要找到与给定输入文档相似的所有文档。显然,对于这种类型的查询,输入文档本身应该是其最佳匹配。原因主要是根据Lucene评分公式,由于具有最高tf-idf的术语。因此,输入文档中具有最高tf-idf的术语是该文档的良好代表,并且可以在析取查询(或OR)中使用以检索相似文档。MLT查询简单地从输入文档中提取文本,对其进行分析,通常使用与字段相同的分析器,然后选择具有最高tf-idf的前K个术语来形成这些术语的析取查询。

要执行MLT的字段必须被索引并且类型为textkeyword。此外,当使用like与文档时,必须启用_source或字段必须被stored或存储term_vector。为了加快分析速度,在索引时存储词向量可能会有所帮助。

例如,如果我们希望对“title”和“tags.raw”字段执行MLT,我们可以在索引时显式存储它们的term_vector。我们仍然可以对“description”和“tags”字段执行MLT,因为默认情况下启用了_source,但对于这些字段,分析速度不会加快。

PUT /imdb
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "term_vector": "yes"
      },
      "description": {
        "type": "text"
      },
      "tags": {
        "type": "text",
        "fields": {
          "raw": {
            "type": "text",
            "analyzer": "keyword",
            "term_vector": "yes"
          }
        }
      }
    }
  }
}

参数

edit

唯一必需的参数是like,所有其他参数都有合理的默认值。参数分为三种类型:一种用于指定文档输入,另一种用于术语选择和查询形成。

文档输入参数

edit

like

MLT查询的唯一必需参数是like,并且遵循一种多功能的语法,用户可以指定自由形式的文本和/或单个或多个文档(见上文示例)。指定文档的语法类似于Multi GET API使用的语法。在指定文档时,文本从fields中获取,除非在每个文档请求中被覆盖。文本由字段的分析器进行分析,但也可以被覆盖。覆盖字段分析器的语法类似于Term Vectors APIper_field_analyzer参数的语法。此外,为了提供不一定存在于索引中的文档,还支持人工文档

不像

unlike 参数与 like 一起使用,以避免选择在选定文档集中找到的术语。换句话说,我们可以要求文档 like: "Apple",但 unlike: "cake crumble tree"。语法与 like 相同。

字段

要获取和分析文本的字段列表。默认为 index.query.default_field 索引设置,其默认值为 ** 值匹配所有符合 term-level queries 条件的字段,不包括元数据字段。

术语选择参数

edit

max_query_terms

将选择的查询词的最大数量。增加此值会以查询执行速度为代价提高准确性。默认为 25

min_term_freq

输入文档中低于此最小词频的词将被忽略。默认为 2

min_doc_freq

输入文档中低于此最小文档频率的术语将被忽略。默认为 5

max_doc_freq

输入文档中将被忽略的术语的最大文档频率。这可能有助于忽略高频词,例如停用词。默认为无界(Integer.MAX_VALUE,即 2^31-1 或 2147483647)。

min_word_length

低于此最小字长阈值的词条将被忽略。默认为 0

max_word_length

忽略术语的最大词长度。默认为无限制(0)。

停用词

一组停用词。在此集合中的任何单词都被认为是“无趣的”并被忽略。如果分析器允许使用停用词,您可能希望告诉MLT明确忽略它们,因为在文档相似性的目的下,假设“停用词永远不有趣”似乎是合理的。

分析器

用于分析自由格式文本的分析器。默认使用与fields中第一个字段关联的分析器。

查询形成参数

edit

minimum_should_match

在析取查询形成后,此参数控制必须匹配的术语数量。 语法与最小应匹配相同。 (默认值为"30%")。

fail_on_unsupported_field

控制查询是否应在任何指定的字段不是支持的类型(textkeyword)时失败(抛出异常)。将此设置为 false 以忽略该字段并继续处理。默认为 true

boost_terms

形成的查询中的每个术语可以通过其tf-idf分数进一步增强。 这设置了使用此功能时的增强因子。默认为 未激活(0)。任何其他正值都会激活术语增强,并使用给定的增强因子。

include

指定输入的文档是否也应包含在返回的搜索结果中。默认为false

boost

设置整个查询的提升值。默认为 1.0

替代方案

edit

为了更精细地控制构建用于查找相似文档的查询,值得考虑编写自定义客户端代码,将示例文档中的选定术语组装成具有所需设置的布尔查询。more_like_this 中用于从一段文本中选择“有趣”单词的逻辑也可以通过 TermVectors API 访问。例如,使用 termvectors API,可以向用户展示文档文本中发现的主题关键词,允许他们选择感兴趣的词语进行深入挖掘,而不是使用 more_like_this 所采用的更“黑箱”的匹配方法。

percolate 查询

edit

The percolate 查询可以用于匹配存储在索引中的查询。percolate 查询本身包含将被用作查询的文档,以与存储的查询进行匹配。

示例用法

edit

为了提供一个简单的示例,本文档使用一个索引, my-index-000001,用于存储 percolate 查询和文档。当只注册了少量 percolate 查询时,这种设置可以很好地工作。对于更重的使用场景,我们建议您将查询和文档存储在不同的索引中。有关更多详细信息,请参阅 How it Works Under the Hood

创建一个包含两个字段的索引:

PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "message": {
        "type": "text"
      },
      "query": {
        "type": "percolator"
      }
    }
  }
}

The message 字段是用于在将文档定义的 percolator 查询预处理后,将其索引到临时索引中的字段。

The query 字段用于索引查询文档。它将保存一个表示实际 Elasticsearch 查询的 json 对象。query 字段已配置为使用 percolator 字段类型。此字段类型理解查询 DSL 并以一种可以在以后用于匹配 percolate 查询中定义的文档的方式存储查询。

在 percolator 中注册一个查询:

PUT /my-index-000001/_doc/1?refresh
{
  "query": {
    "match": {
      "message": "bonsai tree"
    }
  }
}

将文档与已注册的 percolator 查询进行匹配:

GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "message": "A new bonsai tree in the office"
      }
    }
  }
}

上述请求将产生以下响应:

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.26152915,
    "hits": [
      { 
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 0.26152915,
        "_source": {
          "query": {
            "match": {
              "message": "bonsai tree"
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0] 
        }
      }
    ]
  }
}

ID为1的查询与我们的文档匹配。

The _percolator_document_slot 字段表示哪个文档与此查询匹配。 在同时过滤多个文档时非常有用。

参数

edit

以下参数在渗透文档时是必需的:

字段

类型为 percolator 的字段,用于保存索引查询。这是一个必填参数。

名称

在指定了多个percolate查询的情况下,用于_percolator_document_slot字段的后缀。 这是一个可选参数。

文档

正在渗透的文档的来源。

文档

类似于document参数,但通过json数组接受多个文档。

文档类型

正在被 percolated 的文档的类型 / 映射。此参数已弃用,并将在 Elasticsearch 8.0 中移除。

不需要指定被筛选文档的来源,也可以从已存储的文档中获取来源。percolate 查询将在内部执行一个获取请求来获取该文档。

在这种情况下,document 参数可以用以下参数替代:

索引

文档所在的索引。这是一个必需的参数。

类型

要获取的文档类型。此参数已弃用,并将在 Elasticsearch 8.0 中移除。

id

要获取的文档的ID。这是一个必需的参数。

路由

可选地,使用路由来获取要过滤的文档。

preference

可选地,用于获取要过滤的文档的偏好。

版本

可选地,要获取的文档的预期版本。

在过滤上下文中的渗透

edit

如果你对分数不感兴趣,可以通过将 percolator 查询包装在 bool 查询的过滤子句中或在一个 constant_score 查询中来获得更好的性能:

GET /my-index-000001/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "percolate": {
          "field": "query",
          "document": {
            "message": "A new bonsai tree in the office"
          }
        }
      }
    }
  }
}

在索引时,术语从percolator查询中提取,percolator通常可以通过查看这些提取的术语来确定查询是否匹配。然而,计算分数需要反序列化每个匹配的查询并将其与渗透的文档进行比较,这是一个更昂贵的操作。因此,如果不需要计算分数,percolate查询应该被包装在一个constant_score查询或bool查询的过滤子句中。

请注意,percolate 查询永远不会被查询缓存所缓存。

渗透多个文档

edit

The percolate 查询可以使用索引的 percolator 查询同时匹配多个文档。 在单个请求中 percolating 多个文档可以提高性能,因为查询只需要解析和匹配一次,而不是多次。

当同时过滤多个文档时,与每个匹配的过滤器查询一起返回的_percolator_document_slot字段非常重要。它指示哪些文档与特定的过滤器查询匹配。这些数字与percolate查询中指定的documents数组中的槽相关联。

GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [ 
        {
          "message": "bonsai tree"
        },
        {
          "message": "new tree"
        },
        {
          "message": "the office"
        },
        {
          "message": "office tree"
        }
      ]
    }
  }
}

documents 数组包含 4 个文档,这些文档将同时进行 percolate 操作。

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.7093853,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 0.7093853,
        "_source": {
          "query": {
            "match": {
              "message": "bonsai tree"
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0, 1, 3] 
        }
      }
    ]
  }
}

The _percolator_document_slot 表示在 percolate 查询中指定的第一个、第二个和最后一个文档与此查询匹配。

渗透现有文档

edit

为了过滤新索引的文档,可以使用percolate查询。根据索引请求的响应,可以使用_id和其他元信息立即过滤新添加的文档。

示例

edit

基于前面的示例。

索引我们想要渗透的文档:

PUT /my-index-000001/_doc/2
{
  "message" : "A new bonsai tree in the office"
}

索引响应:

{
  "_index": "my-index-000001",
  "_id": "2",
  "_version": 1,
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "result": "created",
  "_seq_no" : 1,
  "_primary_term" : 1
}

使用索引响应作为基础来构建新的搜索请求,对现有文档进行渗透:

GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "index": "my-index-000001",
      "id": "2",
      "version": 1 
    }
  }
}

版本是可选的,但在某些情况下很有用。我们可以确保我们正在尝试渗透我们刚刚索引的文档。在我们索引之后可能会进行更改,如果是这种情况,搜索请求将以版本冲突错误失败。

搜索响应返回的内容与前一个示例相同。

渗透查询和突出显示

edit

当涉及到高亮显示时,percolate 查询的处理方式是特殊的。查询的命中结果用于高亮显示在 percolate 查询中提供的文档。而在常规的高亮显示中,搜索请求中的查询用于高亮显示命中结果。

示例

edit

此示例基于第一个示例的映射。

保存查询:

PUT /my-index-000001/_doc/3?refresh
{
  "query": {
    "match": {
      "message": "brown fox"
    }
  }
}

保存另一个查询:

PUT /my-index-000001/_doc/4?refresh
{
  "query": {
    "match": {
      "message": "lazy dog"
    }
  }
}

执行一个带有percolate查询和启用高亮的搜索请求:

GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "message": "The quick brown fox jumps over the lazy dog"
      }
    }
  },
  "highlight": {
    "fields": {
      "message": {}
    }
  }
}

这将产生以下响应。

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 2,
        "relation": "eq"
    },
    "max_score": 0.26152915,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "3",
        "_score": 0.26152915,
        "_source": {
          "query": {
            "match": {
              "message": "brown fox"
            }
          }
        },
        "highlight": {
          "message": [
            "The quick <em>brown</em> <em>fox</em> jumps over the lazy dog" 
          ]
        },
        "fields" : {
          "_percolator_document_slot" : [0]
        }
      },
      {
        "_index": "my-index-000001",
        "_id": "4",
        "_score": 0.26152915,
        "_source": {
          "query": {
            "match": {
              "message": "lazy dog"
            }
          }
        },
        "highlight": {
          "message": [
            "The quick brown fox jumps over the <em>lazy</em> <em>dog</em>" 
          ]
        },
        "fields" : {
          "_percolator_document_slot" : [0]
        }
      }
    ]
  }
}

每个查询中的术语已在文档中高亮显示。

与在搜索请求中高亮显示 percolator 命中的查询不同,percolator 查询会高亮显示在 percolate 查询中定义的文档。

当同时渗透多个文档时,如下面的请求所示,高亮响应会有所不同:

GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [
        {
          "message": "bonsai tree"
        },
        {
          "message": "new tree"
        },
        {
          "message": "the office"
        },
        {
          "message": "office tree"
        }
      ]
    }
  },
  "highlight": {
    "fields": {
      "message": {}
    }
  }
}

稍微不同的响应:

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.7093853,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 0.7093853,
        "_source": {
          "query": {
            "match": {
              "message": "bonsai tree"
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0, 1, 3]
        },
        "highlight" : { 
          "0_message" : [
              "<em>bonsai</em> <em>tree</em>"
          ],
          "3_message" : [
              "office <em>tree</em>"
          ],
          "1_message" : [
              "new <em>tree</em>"
          ]
        }
      }
    ]
  }
}

高亮字段已根据它们所属的文档槽位进行了前缀处理,以便了解哪个高亮字段属于哪个文档。

在 percolator 查询中的命名查询

edit

如果一个存储的 percolator 查询是一个复杂查询,并且您想要跟踪其子查询匹配了哪个 percolated 文档,那么您可以使用其子查询的 \_name 参数。在这种情况下,在响应中,每个命中连同 _percolator_document_slot 字段一起包含 _percolator_document_slot__matched_queries 字段,这些字段显示了哪些子查询匹配了每个 percolated 文档。

例如:

PUT /my-index-000001/_doc/5?refresh
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "message": {
              "query": "Japanese art",
              "_name": "query1"
            }
          }
        },
        {
          "match": {
            "message": {
              "query": "Holand culture",
              "_name": "query2"
            }
          }
        }
      ]
    }
  }
}
GET /my-index-000001/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [
        {
          "message": "Japanse art"
        },
        {
          "message": "Holand culture"
        },
        {
          "message": "Japanese art and Holand culture"
        },
        {
          "message": "no-match"
        }
      ]
    }
  }
}
{
  "took": 55,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 1.1181908,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "5",
        "_score": 1.1181908,
        "_source": {
          "query": {
            "bool": {
              "should": [
                {
                  "match": {
                    "message": {
                      "query": "Japanese art",
                      "_name": "query1"
                    }
                  }
                },
                {
                  "match": {
                    "message": {
                      "query": "Holand culture",
                      "_name": "query2"
                    }
                  }
                }
              ]
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0, 1, 2],
          "_percolator_document_slot_0_matched_queries" : ["query1"], 
          "_percolator_document_slot_1_matched_queries" : ["query2"], 
          "_percolator_document_slot_2_matched_queries" : ["query1", "query2"] 
        }
      }
    ]
  }
}

第一个文档仅匹配了第一个子查询。

第二个文档仅匹配了第二个子查询。

第三个文档同时匹配了两个子查询。

指定多个渗透查询

edit

可以在单个搜索请求中指定多个percolate查询:

GET /my-index-000001/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "percolate": {
            "field": "query",
            "document": {
              "message": "bonsai tree"
            },
            "name": "query1" 
          }
        },
        {
          "percolate": {
            "field": "query",
            "document": {
              "message": "tulip flower"
            },
            "name": "query2" 
          }
        }
      ]
    }
  }
}

参数name将用于识别哪些percolator文档槽属于哪个percolate查询。

字段名称 _percolator_document_slot 将附加在 _name 参数中指定的内容之后。 如果没有指定,则将使用 field 参数,在这种情况下会导致歧义。

上述搜索请求返回的响应类似于以下内容:

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.26152915,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 0.26152915,
        "_source": {
          "query": {
            "match": {
              "message": "bonsai tree"
            }
          }
        },
        "fields" : {
          "_percolator_document_slot_query1" : [0] 
        }
      }
    ]
  }
}

字段 _percolator_document_slot_query1 表示这些匹配的槽位来自 percolate 查询,其中 _name 参数设置为 query1

工作原理揭秘

edit

当将文档索引到一个已配置了percolator字段类型映射的索引时,文档的查询部分会被解析为Lucene查询并存储到Lucene索引中。查询的二进制表示形式会被存储,但查询的术语也会被分析并存储到一个索引字段中。

在搜索时,请求中指定的文档会被解析为Lucene文档并存储在内存中的临时Lucene索引中。这个内存中的索引只能保存这一个文档,并且针对此进行了优化。之后,基于内存索引中的术语构建一个特殊查询,该查询根据其索引的查询术语选择候选的percolator查询。然后,内存索引会评估这些查询是否实际匹配。

选择候选渗透器查询匹配项是执行percolate查询期间的一个重要性能优化,因为它可以显著减少内存索引需要评估的候选匹配项数量。percolate查询能够实现这一点的原因是,在索引渗透器查询期间,查询词被提取并与渗透器查询一起索引。不幸的是,渗透器无法从所有查询中提取词(例如wildcardgeo_shape查询),因此在某些情况下,渗透器无法进行选择优化(例如,如果布尔查询的必需子句中定义了不支持的查询,或者渗透器文档中唯一查询是不支持的查询)。这些查询被渗透器标记,可以通过运行以下搜索来找到:

GET /_search
{
  "query": {
    "term" : {
      "query.extraction_result" : "failed"
    }
  }
}

上述示例假设映射中存在一个类型为 percolatorquery 字段。

鉴于渗透设计,通常使用单独的索引来存储渗透查询和被渗透的文档是有意义的,而不是像我们在示例中那样使用单一索引。这种方法有几个好处:

  • 因为 percolate 查询包含与 percolated 文档不同的字段集,使用两个单独的索引可以更密集、更高效地存储字段。
  • Percolate 查询的扩展方式与其他查询不同,因此使用不同的索引配置(如主分片数量)可能会提高 percolation 性能。

注释

edit

允许昂贵的查询

edit

如果 search.allow_expensive_queries 设置为 false,则不会执行 percolate 查询。

使用自定义相似性

edit

渗透查询将不会遵循任何配置的自定义相似性。它们始终使用默认的Lucene相似性。

排名特征查询

edit

基于rank_featurerank_features字段的数值,提升文档的相关性评分

The rank_feature 查询通常用于 bool 查询的 should 子句中,以便将其相关性评分添加到 bool 查询中的其他评分中。

对于rank_featurerank_features字段,如果positive_score_impact设置为false,我们建议参与查询的每个文档都为此字段设置一个值。否则,如果在should子句中使用了rank_feature查询,它不会为缺少该值的文档增加任何分数,但会为包含该特征的文档增加一些提升。这与我们想要的相反——因为我们认为这些特征是负面的,我们希望将包含它们的文档排名低于缺少它们的文档。

function_score查询或其他改变相关性分数的方法不同,rank_feature查询在track_total_hits参数不是true时,能够高效地跳过非竞争性的命中结果。这可以显著提高查询速度。

排名特征函数

edit

要基于排名特征字段计算相关性得分,rank_feature查询支持以下数学函数:

如果你不知道从哪里开始,我们推荐使用saturation函数。如果没有提供函数,rank_feature查询默认使用saturation函数。

示例请求

edit

索引设置

edit

要使用 rank_feature 查询,您的索引必须包含一个 rank_featurerank_features 字段映射。要了解如何为 rank_feature 查询设置索引,请尝试以下示例。

创建一个包含以下字段映射的 test 索引:

  • pagerank,一个rank_feature字段,用于衡量网站的重要性
  • url_length,一个rank_feature字段,包含网站URL的长度。在这个例子中,长URL与相关性呈负相关,由positive_score_impact值为false表示。
  • topics,一个rank_features字段,包含一个主题列表以及每个文档与该主题的连接程度的度量
PUT /test
{
  "mappings": {
    "properties": {
      "pagerank": {
        "type": "rank_feature"
      },
      "url_length": {
        "type": "rank_feature",
        "positive_score_impact": false
      },
      "topics": {
        "type": "rank_features"
      }
    }
  }
}

将多个文档索引到test索引中。

PUT /test/_doc/1?refresh
{
  "url": "https://en.wikipedia.org/wiki/2016_Summer_Olympics",
  "content": "Rio 2016",
  "pagerank": 50.3,
  "url_length": 42,
  "topics": {
    "sports": 50,
    "brazil": 30
  }
}

PUT /test/_doc/2?refresh
{
  "url": "https://en.wikipedia.org/wiki/2016_Brazilian_Grand_Prix",
  "content": "Formula One motor race held on 13 November 2016",
  "pagerank": 50.3,
  "url_length": 47,
  "topics": {
    "sports": 35,
    "formula one": 65,
    "brazil": 20
  }
}

PUT /test/_doc/3?refresh
{
  "url": "https://en.wikipedia.org/wiki/Deadpool_(film)",
  "content": "Deadpool is a 2016 American superhero film",
  "pagerank": 50.3,
  "url_length": 37,
  "topics": {
    "movies": 60,
    "super hero": 65
  }
}

示例查询

edit

以下查询搜索 2016 并根据 pagerankurl_lengthsports 主题提升相关性分数。

GET /test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "2016"
          }
        }
      ],
      "should": [
        {
          "rank_feature": {
            "field": "pagerank"
          }
        },
        {
          "rank_feature": {
            "field": "url_length",
            "boost": 0.1
          }
        },
        {
          "rank_feature": {
            "field": "topics.sports",
            "boost": 0.4
          }
        }
      ]
    }
  }
}

用于rank_feature的顶级参数

edit
field
(必需,字符串) 用于提升 rank_featurerank_features 字段的 相关性评分
boost

(可选, 浮点数) 用于减少或增加 相关性分数的浮点数。默认为 1.0

Boost值相对于默认值1.0是相对的。Boost值在01.0之间会降低相关性分数。大于1.0的值会增加相关性分数。

saturation

(可选, 函数对象) 用于基于排名特征字段的值来提升相关性分数的饱和函数。如果没有提供函数,rank_feature查询默认使用saturation函数。更多信息请参见饱和度

只能提供一个函数 saturationlogsigmoidlinear

log

(可选, 函数对象) 对数函数用于基于排名特征字段的值来提升相关性分数。更多信息请参见对数

只能提供一个函数 saturationlogsigmoidlinear

sigmoid

(可选, 函数对象) 用于基于排名特征field的值提升相关性分数的Sigmoid函数。更多信息请参见Sigmoid

只能提供一个函数 saturationlogsigmoidlinear

linear

(可选, 函数对象) 用于基于排名特征字段的值提升相关性分数的线性函数。更多信息请参见线性

只能提供一个函数 saturationlogsigmoidlinear

注释

edit

饱和度

edit

The saturation 函数给出一个等于 S / (S + pivot) 的分数,其中 S 是 排名特征字段的值,pivot 是一个可配置的枢轴值, 因此如果 S 小于枢轴,结果将小于 0.5,否则将大于 0.5。分数总是 (0,1)

如果排名特征对分数有负面影响,那么函数将计算为 pivot / (S + pivot),随着 S 的增加而减少。

GET /test/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank",
      "saturation": {
        "pivot": 8
      }
    }
  }
}

如果没有提供pivot值,Elasticsearch会计算一个默认值,该值等于索引中所有rank feature值的近似几何平均值。如果你没有机会训练一个好的pivot值,我们建议使用这个默认值。

GET /test/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank",
      "saturation": {}
    }
  }
}

对数

edit

The log 函数给出一个等于 log(scaling_factor + S) 的分数,其中 S 是排名特征字段的值,scaling_factor 是一个可配置的缩放因子。分数是无界的。

此函数仅支持对得分有正面影响的排名特征。

GET /test/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank",
      "log": {
        "scaling_factor": 4
      }
    }
  }
}

Sigmoid

edit

The sigmoid 函数是 saturation 的扩展,它增加了一个可配置的指数。分数的计算公式为 S^exp^ / (S^exp^ + pivot^exp^)。与 saturation 函数类似,pivot 是使分数为 0.5S 值,分数范围为 (0,1)

指数exponent必须为正数,通常在[0.5, 1]范围内。一个好的值应该通过训练来计算。如果你没有机会这样做,我们建议你使用saturation函数代替。

GET /test/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank",
      "sigmoid": {
        "pivot": 7,
        "exponent": 0.6
      }
    }
  }
}

线性

edit

The linear 函数是最简单的函数,并且给出的分数等于 S 的索引值,其中 S 是 rank feature 字段的值。 如果一个 rank feature 字段被索引为 "positive_score_impact": true, 它的索引值等于 S 并且四舍五入以保留仅 9 位有效位以保证精度。 如果一个 rank feature 字段被索引为 "positive_score_impact": false, 它的索引值等于 1/S 并且四舍五入以保留仅 9 位有效位以保证精度。

GET /test/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank",
      "linear": {}
    }
  }
}

脚本查询

edit

运行时字段提供了一个非常相似的功能,更加灵活。您编写脚本来创建字段值,并且它们可以在任何地方使用,例如字段所有查询聚合

根据提供的脚本过滤文档。script查询通常用于过滤上下文中。

使用脚本可能导致搜索速度变慢。请参阅 脚本、缓存和搜索速度

示例请求

edit
GET /_search
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": """
            double amount = doc['amount'].value;
            if (doc['type'].value == 'expense') {
              amount *= -1;
            }
            return amount < 10;
          """
        }
      }
    }
  }
}

您可以通过使用运行时字段在搜索查询中实现相同的结果。使用fields参数在_search API上获取作为同一查询一部分的值:

GET /_search
{
  "runtime_mappings": {
    "amount.signed": {
      "type": "double",
      "script": """
        double amount = doc['amount'].value;
        if (doc['type'].value == 'expense') {
          amount *= -1;
        }
        emit(amount);
      """
    }
  },
  "query": {
    "bool": {
      "filter": {
        "range": {
          "amount.signed": { "lt": 10 }
        }
      }
    }
  },
  "fields": [{"field": "amount.signed"}]
}

脚本的顶级参数

edit
script
(必需,脚本对象) 包含一个作为查询运行的脚本。此脚本必须返回一个布尔值,truefalse

注释

edit

自定义参数

edit

过滤器一样,脚本会被缓存以加快执行速度。 如果您频繁更改脚本的参数,我们建议您将它们存储在脚本的params参数中。例如:

GET /_search
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": "doc['num1'].value > params.param1",
            "lang": "painless",
            "params": {
              "param1": 5
            }
          }
        }
      }
    }
  }
}

允许昂贵的查询

edit

如果 search.allow_expensive_queries 设置为 false,脚本查询将不会被执行。

脚本评分查询

edit

使用一个脚本为返回的文档提供自定义评分。

如果例如,一个评分函数很昂贵,并且你只需要计算过滤后的文档集的分数,那么script_score查询就很有用。

示例请求

edit

以下 script_score 查询为每个返回的文档分配一个分数,该分数等于 my-int 字段值除以 10

GET /_search
{
  "query": {
    "script_score": {
      "query": {
        "match": { "message": "elasticsearch" }
      },
      "script": {
        "source": "doc['my-int'].value / 10 "
      }
    }
  }
}

用于script_score的顶级参数

edit
query
(必需,查询对象) 用于返回文档的查询。
script

(必需的, 脚本对象) 用于计算由 query 返回的文档的分数的脚本。

来自 script_score 查询的最终相关性评分不能为负数。为了支持某些搜索优化,Lucene 要求评分必须为正数或 0

min_score
(可选, 浮点数) 得分低于此浮点数的文档将从搜索结果中排除。
boost
(可选, 浮点数) 由 script 生成的文档分数会乘以 boost 以生成最终的文档分数。默认为 1.0

注释

edit

在脚本中使用相关性分数

edit

在脚本中,您可以 访问 _score 变量,该变量表示文档的当前相关性得分。

预定义函数

edit

您可以在您的script中使用任何可用的painless函数。您还可以使用以下预定义函数来自定义评分:

我们建议使用这些预定义函数,而不是编写自己的函数。 这些函数利用了 Elasticsearch 内部机制的效率。

饱和度
edit

saturation(value,k) = value/(k + value)

"script" : {
    "source" : "saturation(doc['my-int'].value, 1)"
}
Sigmoid
edit

sigmoid(value, k, a) = value^a/ (k^a + value^a)

"script" : {
    "source" : "sigmoid(doc['my-int'].value, 2, 1)"
}
随机评分函数
edit

random_score 函数生成从0到1(不包括1)均匀分布的分数。

randomScore 函数具有以下语法: randomScore(, )。 它有一个必需的参数 - seed 作为整数值, 和一个可选的参数 - fieldName 作为字符串值。

"script" : {
    "source" : "randomScore(100, '_seq_no')"
}

如果省略了fieldName参数,将使用内部Lucene文档ID作为随机性的来源。这是非常高效的,但不幸的是,由于文档可能会在合并过程中重新编号,因此无法重现。

"script" : {
    "source" : "randomScore(100)"
}

请注意,位于同一分片中且具有相同字段值的文档将获得相同的分数,因此通常希望使用一个在分片中的所有文档中具有唯一值的字段。一个好的默认选择可能是使用_seq_no字段,其唯一缺点是如果文档被更新,分数将会改变,因为更新操作也会更新_seq_no字段的值。

数值字段的衰减函数
edit

您可以在此处阅读更多关于衰减函数的信息 here.

  • double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue)
  • double decayNumericExp(double origin, double scale, double offset, double decay, double docValue)
  • double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)
"script" : {
    "source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
    "params": { 
        "origin": 20,
        "scale": 10,
        "decay" : 0.5,
        "offset" : 0
    }
}

使用params允许即使参数改变也只编译脚本一次。

地理字段的衰减函数
edit
  • double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
  • double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
  • double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
"script" : {
    "source" : "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
    "params": {
        "origin": "40, -70.12",
        "scale": "200km",
        "offset": "0km",
        "decay" : 0.2
    }
}
日期字段的衰减函数
edit
  • double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
  • double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
  • double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
"script" : {
    "source" : "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
    "params": {
        "origin": "2008-01-01T01:00:00Z",
        "scale": "1h",
        "offset" : "0",
        "decay" : 0.5
    }
}

日期上的衰减函数仅限于默认格式和默认时区的日期。此外,不支持使用now进行计算。

向量字段的函数
edit

向量字段的函数 可以通过 script_score 查询访问。

允许昂贵的查询

edit

如果 search.allow_expensive_queries 设置为 false,脚本评分查询将不会被执行。

更快的替代方案

edit

The script_score 查询计算每个匹配文档或命中的分数。有一些更快的替代查询类型可以有效地跳过非竞争性命中:

  • 如果你想在某些静态字段上提升文档的排名,请使用 rank_feature 查询。
  • 如果你想提升更接近某个日期或地理位置的文档的排名,请使用 distance_feature 查询。

从函数评分查询的过渡

edit

我们建议使用 script_score 查询,而不是 function_score 查询,因为 script_score 查询更简单。

您可以使用 script_score 查询来实现 function_score 查询的以下功能:

script_score
edit

在 Function Score 查询中使用的 script_score,你可以直接复制到 Script Score 查询中。这里不需要做任何改动。

weight
edit

weight 函数可以通过以下脚本在 Script Score 查询中实现:

"script" : {
    "source" : "params.weight * _score",
    "params": {
        "weight": 2
    }
}
random_score
edit

使用 randomScore 函数,如 随机评分函数 中所述。

field_value_factor
edit

field_value_factor 函数可以通过脚本轻松实现:

"script" : {
    "source" : "Math.log10(doc['field'].value * params.factor)",
    "params" : {
        "factor" : 5
    }
}

要检查文档是否缺少某个值,可以使用 doc['field'].size() == 0。例如,如果文档没有字段 field,此脚本将使用值 1

"script" : {
    "source" : "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
    "params" : {
        "factor" : 5
    }
}

此表列出了如何通过脚本实现 field_value_factor 修饰符:

Modifier Implementation in Script Score

-

日志

Math.log10(doc['f'].value)

log1p

Math.log10(doc['f'].value + 1)

log2p

Math.log10(doc['f'].value + 2)

ln

Math.log(doc['f'].value)

ln1p

Math.log(doc['f'].value + 1)

ln2p

Math.log(doc['f'].value + 2)

平方

Math.pow(doc['f'].value, 2)

sqrt

Math.sqrt(doc['f'].value)

倒数

1.0 / doc['f'].value

衰减函数
edit

The script_score query has equivalent decay functions that can be used in scripts.

向量字段的函数

edit

在向量函数的计算过程中,所有匹配的文档都会被线性扫描。因此,查询时间会随着匹配文档数量的增加而线性增长。出于这个原因,我们建议使用query参数来限制匹配文档的数量。

这是可用向量函数和向量访问方法的列表:

  1. cosineSimilarity – 计算余弦相似度
  2. dotProduct – 计算点积
  3. l1norm – 计算L1距离
  4. hamming – 计算汉明距离
  5. l2norm - 计算L2距离
  6. doc[].vectorValue – 返回向量的值作为浮点数数组
  7. doc[].magnitude – 返回向量的幅度

对于bit向量,不支持cosineSimilaritydotProduct函数。

访问密集向量的推荐方法是使用 cosineSimilaritydotProductl1norml2norm 函数。但请注意,您应该在每个脚本中仅调用这些函数一次。例如,不要在循环中使用这些函数来计算文档向量与多个其他向量之间的相似性。如果您需要该功能,请通过 直接访问向量值 自行重新实现这些函数。

让我们创建一个带有 dense_vector 映射的索引,并将其索引几个文档。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_dense_vector": {
        "type": "dense_vector",
        "index": false,
        "dims": 3
      },
      "my_byte_dense_vector": {
        "type": "dense_vector",
        "index": false,
        "dims": 3,
        "element_type": "byte"
      },
      "status" : {
        "type" : "keyword"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "my_dense_vector": [0.5, 10, 6],
  "my_byte_dense_vector": [0, 10, 6],
  "status" : "published"
}

PUT my-index-000001/_doc/2
{
  "my_dense_vector": [-0.5, 10, 10],
  "my_byte_dense_vector": [0, 10, 10],
  "status" : "published"
}

POST my-index-000001/_refresh
余弦相似度
edit

函数 cosineSimilarity 计算给定查询向量与文档向量之间的余弦相似度度量。

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published" 
            }
          }
        }
      },
      "script": {
        "source": "cosineSimilarity(params.query_vector, 'my_dense_vector') + 1.0", 
        "params": {
          "query_vector": [4, 3.4, -0.2]  
        }
      }
    }
  }
}

要限制应用脚本评分计算的文档数量,请提供一个过滤器。

该脚本将1.0加到余弦相似度上,以防止分数为负。

为了利用脚本优化,请将查询向量作为脚本参数提供。

如果文档的密集向量字段的维度数量与查询向量的维度不同,将会抛出一个错误。

点积
edit

函数 dotProduct 计算给定查询向量与文档向量之间的点积度量。

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": """
          double value = dotProduct(params.query_vector, 'my_dense_vector');
          return sigmoid(1, Math.E, -value); 
        """,
        "params": {
          "query_vector": [4, 3.4, -0.2]
        }
      }
    }
  }
}

使用标准的sigmoid函数可以防止分数为负数。

L1距离(曼哈顿距离)
edit

函数 l1norm 计算给定查询向量和文档向量之间的 L1 距离(曼哈顿距离)。

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l1norm(params.queryVector, 'my_dense_vector'))", 
        "params": {
          "queryVector": [4, 3.4, -0.2]
        }
      }
    }
  }
}

与表示相似性的cosineSimilarity不同,下面显示的l1norml2norm表示距离或差异。这意味着,向量越相似,l1norml2norm函数产生的分数就越低。因此,由于我们需要更相似的向量来获得更高的分数,我们反转了l1norml2norm的输出。此外,为了避免当文档向量与查询完全匹配时分母为0,我们在分母中加上了1

汉明距离
edit

函数计算给定查询向量与文档向量之间的汉明距离。它仅适用于字节和位向量。

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "(24 - hamming(params.queryVector, 'my_byte_dense_vector')) / 24", 
        "params": {
          "queryVector": [4, 3, 0]
        }
      }
    }
  }
}

计算汉明距离并将其归一化到比特位数,以得到一个介于0和1之间的分数。

L2距离(欧几里得距离)
edit

函数 l2norm 计算给定查询向量与文档向量之间的 L2 距离(欧几里得距离)。

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l2norm(params.queryVector, 'my_dense_vector'))",
        "params": {
          "queryVector": [4, 3.4, -0.2]
        }
      }
    }
  }
}
检查缺失值
edit

如果文档在执行向量函数的向量字段上没有值,将会抛出一个错误。

你可以检查一个文档是否在字段 my_vector 上有值,使用 doc['my_vector'].size() == 0。你的整体脚本可以看起来像这样:

"source": "doc['my_vector'].size() == 0 ? 0 : cosineSimilarity(params.queryVector, 'my_vector')"
直接访问向量
edit

您可以通过以下函数直接访问向量值:

  • doc[].vectorValue – 返回一个向量的值作为浮点数数组

对于向量,它返回一个浮点数[],其中每个元素代表8位。

  • doc[].magnitude – 返回一个向量的幅度作为浮点数 (对于7.5版本之前创建的向量,幅度不会被存储。 因此,每次调用此函数时都会重新计算)。

对于向量,这只是1位总和的平方根。

例如,下面的脚本使用这两个函数实现了余弦相似度:

GET my-index-000001/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": """
          float[] v = doc['my_dense_vector'].vectorValue;
          float vm = doc['my_dense_vector'].magnitude;
          float dotProduct = 0;
          for (int i = 0; i < v.length; i++) {
            dotProduct += v[i] * params.queryVector[i];
          }
          return dotProduct / (vm * (float) params.queryVectorMag);
        """,
        "params": {
          "queryVector": [4, 3.4, -0.2],
          "queryVectorMag": 5.25357
        }
      }
    }
  }
}
位向量和向量函数
edit

当使用向量时,并非所有向量函数都可用。支持的函数有:

  • hamming – 计算汉明距离,即两个向量的按位异或之和
  • l1norm – 计算L1距离,这仅仅是hamming距离
  • l2norm - 计算L2距离,这是hamming距离的平方根

目前,cosineSimilaritydotProduct 函数不支持用于 bit 向量。

解释请求

edit

使用一个解释请求提供了对分数组成部分如何计算的解释。script_score查询可以通过设置explanation参数来添加自己的解释:

GET /my-index-000001/_explain/0
{
  "query": {
    "script_score": {
      "query": {
        "match": { "message": "elasticsearch" }
      },
      "script": {
        "source": """
          long count = doc['count'].value;
          double normalizedCount = count / 10;
          if (explanation != null) {
            explanation.set('normalized count = count / 10 = ' + count + ' / 10 = ' + normalizedCount);
          }
          return normalizedCount;
        """
      }
    }
  }
}

请注意,在使用普通的 _search 请求时,explanation 将为空,因此使用条件保护是最佳实践。

包装查询

edit

一个接受任何其他查询作为base64编码字符串的查询。

GET /_search
{
  "query": {
    "wrapper": {
      "query": "eyJ0ZXJtIiA6IHsgInVzZXIuaWQiIDogImtpbWNoeSIgfX0=" 
    }
  }
}

Base64 编码的字符串: {"term" : { "user.id" : "kimchy" }}

这个查询在Spring Data Elasticsearch的上下文中更有用。它是用户在使用Spring Data仓库时可以添加自定义查询的方式。用户可以在仓库方法上添加@Query()注解。当调用这样的方法时,我们会在注解的查询参数中进行参数替换,然后将此作为搜索请求的查询部分发送。

固定查询

edit

将选定的文档提升到比匹配给定查询的文档更高的排名。 此功能通常用于引导搜索者访问经过策划的文档,这些文档被提升到搜索的任何“自然”匹配之上。 提升或“固定”的文档使用存储在_id字段中的文档ID进行标识。

示例请求

edit
GET /_search
{
  "query": {
    "pinned": {
      "ids": [ "1", "4", "100" ],
      "organic": {
        "match": {
          "description": "iphone"
        }
      }
    }
  }
}

用于pinned的顶级参数

edit
ids
(可选,数组) 文档ID 按其在结果中出现的顺序列出。 如果未指定 docs,则此项为必填。
docs

(可选,数组) 按结果中显示的顺序列出的文档。 如果未指定 ids,则此项为必需。 您可以为每个文档指定以下属性:

_id
(必需,字符串) 唯一的 文档 ID
_index
(可选,字符串) 包含文档的索引。
organic
用于对“固定”文档下方的文档进行排名的任何查询选择。

固定特定索引中的文档

edit

如果你在多个索引中搜索,你可以使用docs在特定索引中固定一个文档:

GET /_search
{
  "query": {
    "pinned": {
      "docs": [
        {
          "_index": "my-index-000001", 
          "_id": "1"
        },
        {
          "_id": "4" 
        }
      ],
      "organic": {
        "match": {
          "description": "iphone"
        }
      }
    }
  }
}

来自 my-index-000001 的文档,其 id 为 1,将是第一个结果。

当缺少_index时,来自查询索引的所有id为4的文档将以相同的分数被固定。

规则查询

edit

rule_query 在 8.15.0 版本中被重命名为 rule。 使用 rule_queryruleset_id 的旧语法已被弃用,并将在未来的版本中移除,因此强烈建议将现有的规则查询迁移到新的 API 结构。

在返回结果之前,将查询规则应用于查询。 查询规则可以用于根据匹配定义的规则以固定查询的方式提升文档,或者识别要从上下文结果集中排除的特定文档。 如果没有定义匹配的查询规则,则返回查询的“自然”匹配结果。 所有匹配的规则按照它们在查询规则集中的顺序应用。 如果同一文档同时匹配exclude规则和pinned规则,则该文档将被排除。

要使用规则查询,您首先需要一组定义的查询规则。 使用查询规则管理API来创建和管理查询规则。 有关更多信息和示例,请参阅使用查询规则进行搜索

示例请求

edit
GET /_search
{
  "query": {
    "rule": {
      "match_criteria": {
        "user_query": "pugs"
      },
      "ruleset_ids": ["my-ruleset"],
      "organic": {
        "match": {
          "description": "puggles"
        }
      }
    }
  }
}

用于rule_query的顶级参数

edit
ruleset_ids
(必需,数组) 一个包含一个或多个唯一 查询规则集 ID 的数组,这些 ID 带有基于查询的规则,以匹配并根据需要应用。 规则集及其关联的规则按照它们在查询和规则集中指定的顺序进行评估。 指定的规则集的最大数量为 10。
match_criteria
(必需,对象) 定义应用于给定查询规则集中规则的匹配条件。 匹配条件应与规则中 criteria.metadata 字段定义的键匹配。
organic
(必需, 对象) 任何选择的 查询 用于返回结果, 可以通过匹配查询规则进行修改。 如果没有匹配和应用任何查询规则, 此查询将以未修改的状态执行。