Knn 查询编辑

查找与查询向量最接近的 k 个向量,通过相似性度量来衡量。knn 查询通过对索引的 dense_vectors 进行近似搜索来查找最近向量。执行近似 kNN 搜索的首选方法是通过搜索请求的 顶级 knn 部分knn 查询专用于需要将此查询与其他查询组合的专家案例。

请求示例编辑

PUT my-image-index
{
  "mappings": {
    "properties": {
       "image-vector": {
        "type": "dense_vector",
        "dims": 3,
        "index": true,
        "similarity": "l2_norm"
      },
      "file-type": {
        "type": "keyword"
      },
      "title": {
        "type": "text"
      }
    }
  }
}
  1. 索引您的数据。

    POST my-image-index/_bulk?refresh=true
    { "index": { "_id": "1" } }
    { "image-vector": [1, 5, -20], "file-type": "jpg", "title": "mountain lake" }
    { "index": { "_id": "2" } }
    { "image-vector": [42, 8, -15], "file-type": "png", "title": "frozen lake"}
    { "index": { "_id": "3" } }
    { "image-vector": [15, 11, 23], "file-type": "jpg", "title": "mountain lake lodge" }
  2. 使用 knn 查询运行搜索,请求前 3 个最近向量。

    response = client.search(
      index: 'my-image-index',
      body: {
        size: 3,
        query: {
          knn: {
            field: 'image-vector',
            query_vector: [
              -5,
              9,
              -12
            ],
            num_candidates: 10
          }
        }
      }
    )
    puts response
    POST my-image-index/_search
    {
      "size" : 3,
      "query" : {
        "knn": {
          "field": "image-vector",
          "query_vector": [-5, 9, -12],
          "num_candidates": 10
        }
      }
    }

knn 查询没有单独的 k 参数。与其他查询类似,k 由搜索请求的 size 参数定义。knn 查询从每个分片收集 num_candidates 个结果,然后合并它们以获得前 size 个结果。

knn 的顶级参数编辑

字段

(必填,字符串)要搜索的向量字段的名称。必须是启用了索引的 dense_vector 字段

query_vector

(可选,浮点数数组或字符串)查询向量。必须与您要搜索的向量字段具有相同的维度数。必须是浮点数数组或十六进制编码的字节向量。必须提供此参数或 query_vector_builder

query_vector_builder

(可选,对象)查询向量构建器。一个配置对象,指示在执行请求之前如何构建 query_vector。您必须提供 query_vector_builderquery_vector,但不能同时提供两者。有关详细信息,请参阅执行语义搜索

num_candidates

(可选,整数)每个分片要考虑的最近邻候选数量。不能超过 10,000。Elasticsearch 从每个分片收集 num_candidates 个结果,然后合并它们以找到最佳结果。增加 num_candidates 往往会提高最终结果的准确性。默认为 Math.min(1.5 * size, 10_000)

过滤器

(可选,查询对象)用于过滤可以匹配的文档的查询。kNN 搜索将返回也与此过滤器匹配的顶部文档。该值可以是单个查询或查询列表。如果未提供 filter,则允许所有文档匹配。

过滤器是一个预过滤器,这意味着它在近似 kNN 搜索期间应用,以确保返回 num_candidates 个匹配文档。

相似度

(可选,浮点数)文档被视为匹配所需的最小相似度。计算出的相似度值与使用的原始 similarity 相关。不是文档分数。然后根据 similarity 对匹配的文档进行评分,并应用提供的 boost

boost

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

_name

(可选,字符串)用于标识查询的名称字段

knn 查询中的预过滤器和后过滤器编辑

有两种方法可以过滤与 kNN 查询匹配的文档

  1. 预过滤 – 在近似 kNN 搜索期间应用过滤器,以确保返回 k 个匹配文档。
  2. 后过滤 – 在近似 kNN 搜索完成后应用过滤器,这会导致结果少于 k 个,即使有足够的匹配文档也是如此。

通过 knn 查询的 filter 参数支持预过滤。来自 别名 的过滤器也作为预过滤器应用。

在查询 DSL 树中找到的所有其他过滤器都作为后过滤器应用。例如,knn 查询查找具有最近向量的顶部 3 个文档 (num_candidates=3),并将它们与作为后过滤器的 term 过滤器组合在一起。最终的文档集将仅包含一个通过后过滤器的文档。

response = client.search(
  index: 'my-image-index',
  body: {
    size: 10,
    query: {
      bool: {
        must: {
          knn: {
            field: 'image-vector',
            query_vector: [
              -5,
              9,
              -12
            ],
            num_candidates: 3
          }
        },
        filter: {
          term: {
            "file-type": 'png'
          }
        }
      }
    }
  }
)
puts response
POST my-image-index/_search
{
  "size" : 10,
  "query" : {
    "bool" : {
      "must" : {
        "knn": {
          "field": "image-vector",
          "query_vector": [-5, 9, -12],
          "num_candidates": 3
        }
      },
      "filter" : {
        "term" : { "file-type" : "png" }
      }
    }
  }
}

使用 knn 查询进行混合搜索编辑

Knn 查询可以用作混合搜索的一部分,其中 knn 查询与其他词法查询相结合。例如,下面的查询查找 titlemountain lake 匹配的文档,并将它们与图像向量最接近 query_vector 的前 10 个文档组合在一起。然后对组合文档进行评分,并返回前 3 个得分最高的文档。

+

POST my-image-index/_search
{
  "size" : 3,
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "mountain lake",
              "boost": 1
            }
          }
        },
        {
          "knn": {
            "field": "image-vector",
            "query_vector": [-5, 9, -12],
            "num_candidates": 10,
            "boost": 2
          }
        }
      ]
    }
  }
}

嵌套查询中的 Knn 查询编辑

knn 查询可以在嵌套查询中使用。这里的行为类似于 顶级嵌套 kNN 搜索

  • 对嵌套 dense_vectors 的 kNN 搜索使顶级文档中的顶级结果多样化
  • 支持对顶级文档元数据的 filter,并将其作为后过滤器
  • 不支持对 nested 字段元数据的 filter

示例查询如下所示

{
  "query" : {
    "nested" : {
      "path" : "paragraph",
        "query" : {
          "knn": {
            "query_vector": [
                0.45,
                45
            ],
            "field": "paragraph.vector",
            "num_candidates": 2
        }
      }
    }
  }
}

具有聚合的 Knn 查询编辑

knn 查询计算来自每个分片的 num_candidates 上的聚合。因此,聚合的最终结果包含 num_candidates * number_of_shards 个文档。这与 顶级 knn 部分 不同,后者在全局前 k 个最近文档上计算聚合。