Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›DSL запросов ›Специализированные запросы

Запрос "Похожие документы"

Запрос "Похожие документы" находит документы, похожие на заданный набор документов. Для этого MLT выбирает набор представительных терминов из этих входных документов, формирует запрос, используя эти термины, выполняет запрос и возвращает результаты. Пользователь контролирует входные документы, способ выбора терминов и формирование запроса.

Простейший случай использования состоит в поиске документов, похожих на предоставленный текст. Здесь мы ищем все фильмы, содержащие текст, похожий на "Однажды в сказке", в полях "title" и "description", ограничивая количество выбранных терминов 12.

resp = client.search(
    query={
        "more_like_this": {
            "fields": [
                "title",
                "description"
            ],
            "like": "Once upon a time",
            "min_term_freq": 1,
            "max_query_terms": 12
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      more_like_this: {
        fields: [
          'title',
          'description'
        ],
        like: 'Once upon a time',
        min_term_freq: 1,
        max_query_terms: 12
      }
    }
  }
)
puts response
const response = await client.search({
  query: {
    more_like_this: {
      fields: ["title", "description"],
      like: "Once upon a time",
      min_term_freq: 1,
      max_query_terms: 12,
    },
  },
});
console.log(response);
GET /_search
{
  "query": {
    "more_like_this" : {
      "fields" : ["title", "description"],
      "like" : "Once upon a time",
      "min_term_freq" : 1,
      "max_query_terms" : 12
    }
  }
}

Более сложный случай использования состоит в смешении текстов с уже существующими в индексе документами. В этом случае синтаксис для указания документа аналогичен синтаксису, используемому в API множественного получения.

resp = client.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
        }
    },
)
print(resp)
response = client.search(
  body: {
    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
      }
    }
  }
)
puts response
const response = await client.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,
    },
  },
});
console.log(response);
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
    }
  }
}

Наконец, пользователи могут смешивать текст, выбранный набор документов, а также предоставлять документы, необязательно присутствующие в индексе. Для предоставления документов, отсутствующих в индексе, используется синтаксис, аналогичный искусственным документам.

resp = client.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
        }
    },
)
print(resp)
response = client.search(
  body: {
    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
      }
    }
  }
)
puts response
const response = await client.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,
    },
  },
});
console.log(response);
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
    }
  }
}

Как это работает

Предположим, мы хотим найти все документы, похожие на заданный входной документ. Очевидно, что сам входной документ должен быть лучшим совпадением для этого типа запроса. Причина в основном, согласно формуле оценки Lucene, связана с терминами с наибольшим tf-idf. Поэтому термины входного документа с наивысшим tf-idf являются хорошими представителями этого документа и могут быть использованы в дизъюнктивном запросе (или OR), чтобы получить похожие документы. Запрос MLT просто извлекает текст из входного документа, анализирует его, обычно с использованием того же анализатора, что и в поле, затем выбирает лучшие K терминов с наибольшим tf-idf для формирования дизъюнктивного запроса из этих терминов.

Поля, на которых должен быть выполнен MLT, должны быть индексированы и иметь тип text или keyword. Кроме того, при использовании like с документами, либо _source должен быть включен, либо поля должны быть stored или хранить term_vector. Для ускорения анализа может помочь хранение векторов терминов во время индексирования.

Например, если мы хотим выполнить MLT на полях "title" и "tags.raw", мы можем явно хранить их term_vector во время индексирования. Мы все еще можем выполнять MLT на полях "description" и "tags", поскольку _source включен по умолчанию, но для этих полей не будет ускорения анализа.

resp = client.indices.create(
    index="imdb",
    mappings={
        "properties": {
            "title": {
                "type": "text",
                "term_vector": "yes"
            },
            "description": {
                "type": "text"
            },
            "tags": {
                "type": "text",
                "fields": {
                    "raw": {
                        "type": "text",
                        "analyzer": "keyword",
                        "term_vector": "yes"
                    }
                }
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'imdb',
  body: {
    mappings: {
      properties: {
        title: {
          type: 'text',
          term_vector: 'yes'
        },
        description: {
          type: 'text'
        },
        tags: {
          type: 'text',
          fields: {
            raw: {
              type: 'text',
              analyzer: 'keyword',
              term_vector: 'yes'
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "imdb",
  mappings: {
    properties: {
      title: {
        type: "text",
        term_vector: "yes",
      },
      description: {
        type: "text",
      },
      tags: {
        type: "text",
        fields: {
          raw: {
            type: "text",
            analyzer: "keyword",
            term_vector: "yes",
          },
        },
      },
    },
  },
});
console.log(response);
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"
          }
        }
      }
    }
  }
}

Параметры

Единственный обязательный параметр - like, все остальные параметры имеют разумные значения по умолчанию. Есть три типа параметров: один для указания входного документа, другой для выбора терминов и формирования запроса.

Параметры входного документа

like

Единственный обязательный параметр запроса MLT - like, и он использует универсальный синтаксис, в котором пользователь может указать свободный текст и/или один или несколько документов (см. примеры выше). Синтаксис для указания документов аналогичен синтаксису, используемому в API множественного получения. При указании документов текст извлекается из fields, если не переопределено в каждом запросе документа. Текст анализируется анализатором в поле, но также может быть переопределен. Синтаксис переопределения анализатора в поле аналогичен параметру per_field_analyzer API векторов терминов. Кроме того, для предоставления документов, необязательно присутствующих в индексе, поддерживаются искусственные документы.

unlike

Параметр unlike используется совместно с like для того, чтобы не выбирать термины, найденные в выбранном наборе документов. Другими словами, мы можем искать документы like: "Apple", но unlike: "cake crumble tree". Синтаксис такой же, как у like.

fields

Список полей для извлечения и анализа текста. По умолчанию соответствует настройке индекса index.query.default_field, которая имеет значение по умолчанию *. Значение * соответствует всем полям, подходящим для запросов на уровне терминов, за исключением метаданных.

Параметры выбора терминов

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).

stop_words

Массив стоп-слов. Любое слово из этого набора считается «неинтересным» и игнорируется. Если анализатор позволяет стоп-слова, вы можете указать MLT на их явное игнорирование, поскольку для целей сходства документов представляется разумным предположить, что «стоп-слово никогда не является интересным».

analyzer

Анализатор, используемый для анализа свободного текста. По умолчанию анализатор, связанный с первым полем в fields.

Параметры формирования запроса

minimum_should_match

После формирования дизъюнктивного запроса этот параметр управляет количеством терминов, которые должны совпадать. Синтаксис аналогичен параметру minimum should match. (По умолчанию "30%").

fail_on_unsupported_field

Управляет тем, должен ли запрос завершиться ошибкой (бросить исключение), если какое-либо из указанных полей не соответствует поддерживаемым типам (text или keyword). Установите это значение в false, чтобы пропустить поле и продолжить обработку. По умолчанию true.

boost_terms

Каждый термин в сформированном запросе может быть дополнительно усилен его tf-idf значением. Это устанавливает коэффициент усиления для использования при использовании этой функции. По умолчанию отключено (0). Любое другое положительное значение активирует усиление терминов с заданным коэффициентом усиления.

include

Указывает, должны ли входные документы также включаться в результаты поиска. По умолчанию false.

boost

Устанавливает значение усиления всего запроса. По умолчанию 1.0.

Альтернатива

Чтобы получить больший контроль над построением запроса к похожим документам, стоит рассмотреть написание пользовательского кода клиента для сборки выбранных терминов из примера документа в булевый запрос с желаемыми настройками. Логика в more_like_this, которая выбирает «интересные» слова из текста, также доступна через API векторов терминов. Например, используя API векторов терминов, можно предоставить пользователям выбор ключевых слов по теме, найденных в тексте документа, позволяя им выбирать интересующие слова для углубленного поиска, а не используя более «черный ящик» подход сопоставления, используемый more_like_this.

© 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-mlt-query.html

Spec-Zone.ru

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