Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Query DSL ›Vector queries

Запрос knn

Находит k ближайших векторов к запросному вектору, измеряемых с помощью метрики сходства. Запрос knn находит ближайшие векторы приближённым поиском по индексированным плотным векторам dense_vectors. Предпочтительный способ выполнения приближённого поиска kNN — через верхний уровень раздела поиска knn в запросе. Запрос knn предназначен для экспертных случаев, когда необходимо объединить этот запрос с другими запросами.

Пример запроса

resp = client.indices.create(
    index="my-image-index",
    mappings={
        "properties": {
            "image-vector": {
                "type": "dense_vector",
                "dims": 3,
                "index": True,
                "similarity": "l2_norm"
            },
            "file-type": {
                "type": "keyword"
            },
            "title": {
                "type": "text"
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'my-image-index',
  body: {
    mappings: {
      properties: {
        "image-vector": {
          type: 'dense_vector',
          dims: 3,
          index: true,
          similarity: 'l2_norm'
        },
        "file-type": {
          type: 'keyword'
        },
        title: {
          type: 'text'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-image-index",
  mappings: {
    properties: {
      "image-vector": {
        type: "dense_vector",
        dims: 3,
        index: true,
        similarity: "l2_norm",
      },
      "file-type": {
        type: "keyword",
      },
      title: {
        type: "text",
      },
    },
  },
});
console.log(response);
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. Индексируйте данные.

    resp = client.bulk(
        index="my-image-index",
        refresh=True,
        operations=[
            {
                "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"
            }
        ],
    )
    print(resp)
    response = client.bulk(
      index: 'my-image-index',
      refresh: true,
      body: [
        {
          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'
        }
      ]
    )
    puts response
    const response = await client.bulk({
      index: "my-image-index",
      refresh: "true",
      operations: [
        {
          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",
        },
      ],
    });
    console.log(response);
    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, запросив 10 ближайших векторов из каждого фрагмента, а затем объедините результаты фрагментов, чтобы получить 3 лучших глобальных результата.

    resp = client.search(
        index="my-image-index",
        size=3,
        query={
            "knn": {
                "field": "image-vector",
                "query_vector": [
                    -5,
                    9,
                    -12
                ],
                "k": 10
            }
        },
    )
    print(resp)
    const response = await client.search({
      index: "my-image-index",
      size: 3,
      query: {
        knn: {
          field: "image-vector",
          query_vector: [-5, 9, -12],
          k: 10,
        },
      },
    });
    console.log(response);
    POST my-image-index/_search
    {
      "size" : 3,
      "query" : {
        "knn": {
          "field": "image-vector",
          "query_vector": [-5, 9, -12],
          "k": 10
        }
      }
    }

Параметры верхнего уровня для knn

field

(Обязательно, строка) Имя поля вектора для поиска. Должно быть полем dense_vector с включённой индексацией.

query_vector

(Необязательно, массив чисел с плавающей точкой или строка) Запросный вектор. Должен иметь такое же количество измерений, что и поле вектора, по которому выполняется поиск. Должен быть либо массивом чисел с плавающей точкой, либо шестнадцатерично закодированным вектором байтов. Должен быть предоставлён либо этот параметр, либо query_vector_builder.

query_vector_builder

(Необязательно, объект) Построитель запросного вектора. Объект конфигурации, указывающий, как построить запрос_вектор перед выполнением запроса. Вы должны предоставить либо query_vector_builder, либо query_vector, но не оба сразу. Дополнительные сведения см. в разделе Выполнение семантического поиска.

k

(Необязательно, целое число) Количество ближайших соседей, возвращаемых из каждого фрагмента. Elasticsearch собирает k результаты из каждого фрагмента, а затем объединяет их, чтобы найти лучшие глобальные результаты. Это значение должно быть меньше или равно num_candidates. По умолчанию равно num_candidates.

num_candidates

(Необязательно, целое число) Количество кандидатов на ближайших соседей, которые следует рассматривать на фрагменте во время поиска knn. Не должно превышать 10 000. Увеличение num_candidates повышает точность конечных результатов. По умолчанию равно 1.5 * k, если установлено k, или 1.5 * size, если k не установлено.

filter

(Необязательно, объект запроса) Запрос для фильтрации документов, которые могут соответствовать. Поиск kNN вернёт лучшие документы, которые также соответствуют этому фильтру. Значение может быть одним запросом или списком запросов. Если filter не указано, все документы могут соответствовать.

Фильтр — это предварительный фильтр, означающий, что он применяется во время приближённого поиска kNN, чтобы гарантировать, что возвращаются документы, num_candidates соответствующие фильтру.

similarity

(Необязательно, число с плавающей точкой) Минимальное сходство, необходимое для того, чтобы документ считался совпадением. Значение сходства, вычисленное, относится к исходному similarity. Не к оценке документа. Совпавшие документы затем оцениваются в соответствии с similarity, и применяется заданное boost.

boost

(Необязательно, число с плавающей точкой) Число с плавающей точкой, используемое для умножения оценок совпадающих документов. Это значение не может быть отрицательным. По умолчанию равно 1.0.

_name

(Необязательно, строка) Поле имени для идентификации запроса

Предварительные и последующие фильтры в запросе knn

Существует два способа фильтрации документов, соответствующих запросу kNN:

  1. предварительный фильтр – фильтр применяется во время приближённого поиска kNN, чтобы гарантировать, что возвращаются только k совпадающие документы.
  2. последующий фильтр – фильтр применяется после завершения приближённого поиска kNN, что приводит к меньшему количеству результатов, чем k, даже когда существует достаточно совпадающих документов.

Предварительный фильтр поддерживается параметром filter запроса knn. Также применяются фильтры из псевдонимов как предварительные фильтры.

Все другие фильтры, найденные в дереве Query DSL, применяются как последующие фильтры. Например, запрос knn находит 3 лучших документа с ближайшими векторами (k=3), которые объединяются с фильтром term, который является последующим фильтром. Конечный набор документов будет содержать только один документ, прошедший последующий фильтр.

resp = client.search(
    index="my-image-index",
    size=10,
    query={
        "bool": {
            "must": {
                "knn": {
                    "field": "image-vector",
                    "query_vector": [
                        -5,
                        9,
                        -12
                    ],
                    "k": 3
                }
            },
            "filter": {
                "term": {
                    "file-type": "png"
                }
            }
        }
    },
)
print(resp)
const response = await client.search({
  index: "my-image-index",
  size: 10,
  query: {
    bool: {
      must: {
        knn: {
          field: "image-vector",
          query_vector: [-5, 9, -12],
          k: 3,
        },
      },
      filter: {
        term: {
          "file-type": "png",
        },
      },
    },
  },
});
console.log(response);
POST my-image-index/_search
{
  "size" : 10,
  "query" : {
    "bool" : {
      "must" : {
        "knn": {
          "field": "image-vector",
          "query_vector": [-5, 9, -12],
          "k": 3
        }
      },
      "filter" : {
        "term" : { "file-type" : "png" }
      }
    }
  }
}

Гибридный поиск с запросом knn

Запрос knn может использоваться как часть гибридного поиска, где запрос knn комбинируется с другими лексическими запросами. Например, запрос ниже находит документы, у которых title соответствует mountain lake, и объединяет их с 10 лучшими документами, имеющими ближайшие векторы изображений к вектору query_vector. Объединённые документы затем оцениваются, и возвращаются 3 лучших документа с наибольшим баллом.

+

resp = client.search(
    index="my-image-index",
    size=3,
    query={
        "bool": {
            "should": [
                {
                    "match": {
                        "title": {
                            "query": "mountain lake",
                            "boost": 1
                        }
                    }
                },
                {
                    "knn": {
                        "field": "image-vector",
                        "query_vector": [
                            -5,
                            9,
                            -12
                        ],
                        "k": 10,
                        "boost": 2
                    }
                }
            ]
        }
    },
)
print(resp)
const response = await client.search({
  index: "my-image-index",
  size: 3,
  query: {
    bool: {
      should: [
        {
          match: {
            title: {
              query: "mountain lake",
              boost: 1,
            },
          },
        },
        {
          knn: {
            field: "image-vector",
            query_vector: [-5, 9, -12],
            k: 10,
            boost: 2,
          },
        },
      ],
    },
  },
});
console.log(response);
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],
            "k": 10,
            "boost": 2
          }
        }
      ]
    }
  }
}

Запрос knn внутри вложенного запроса

Запрос knn может использоваться внутри вложенного запроса. Поведение здесь аналогично поиску kNN на верхнем уровне:

  • Поиск kNN по вложенным dense_vectors диверсифицирует лучшие результаты по документу верхнего уровня
  • filter по метаданным документа верхнего уровня поддерживается и работает как предварительный фильтр
  • filter по метаданным поля nested не поддерживается

Пример запроса может выглядеть так:

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

Запрос knn с агрегациями

Запрос knn вычисляет агрегации по верху k документов из каждого фрагмента. Таким образом, конечные результаты из агрегаций содержат k * number_of_shards документов. Это отличается от верхнего уровня раздела knn, где агрегации рассчитываются по глобальным лучшим k ближайшим документам.

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/query-dsl-knn-query.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API