Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›REST API ›API поиска

Предложения

Предлагает похожие по написанию термины на основе предоставленного текста с помощью предложения.

Новая справка по API

Для получения самых актуальных данных об API, обратитесь к API поиска.

resp = client.search(
    index="my-index-000001",
    query={
        "match": {
            "message": "tring out Elasticsearch"
        }
    },
    suggest={
        "my-suggestion": {
            "text": "tring out Elasticsearch",
            "term": {
                "field": "message"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      match: {
        message: 'tring out Elasticsearch'
      }
    },
    suggest: {
      "my-suggestion": {
        text: 'tring out Elasticsearch',
        term: {
          field: 'message'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  query: {
    match: {
      message: "tring out Elasticsearch",
    },
  },
  suggest: {
    "my-suggestion": {
      text: "tring out Elasticsearch",
      term: {
        field: "message",
      },
    },
  },
});
console.log(response);
POST my-index-000001/_search
{
  "query" : {
    "match": {
      "message": "tring out Elasticsearch"
    }
  },
  "suggest" : {
    "my-suggestion" : {
      "text" : "tring out Elasticsearch",
      "term" : {
        "field" : "message"
      }
    }
  }
}

Запрос

Функция предложений предлагает похожие по написанию термины на основе предоставленного текста, используя предложение. Часть запроса предложений определена вместе с частью запроса в запросе _search. Если часть запроса опущена, возвращаются только предложения.

Примеры

В запросе можно указать несколько предложений. Каждое предложение идентифицируется произвольным именем. В примере ниже запрашиваются два предложения. Оба предложения my-suggest-1 и my-suggest-2 используют предложение term, но имеют разные text.

resp = client.search(
    suggest={
        "my-suggest-1": {
            "text": "tring out Elasticsearch",
            "term": {
                "field": "message"
            }
        },
        "my-suggest-2": {
            "text": "kmichy",
            "term": {
                "field": "user.id"
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    suggest: {
      "my-suggest-1": {
        text: 'tring out Elasticsearch',
        term: {
          field: 'message'
        }
      },
      "my-suggest-2": {
        text: 'kmichy',
        term: {
          field: 'user.id'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  suggest: {
    "my-suggest-1": {
      text: "tring out Elasticsearch",
      term: {
        field: "message",
      },
    },
    "my-suggest-2": {
      text: "kmichy",
      term: {
        field: "user.id",
      },
    },
  },
});
console.log(response);
POST _search
{
  "suggest": {
    "my-suggest-1" : {
      "text" : "tring out Elasticsearch",
      "term" : {
        "field" : "message"
      }
    },
    "my-suggest-2" : {
      "text" : "kmichy",
      "term" : {
        "field" : "user.id"
      }
    }
  }
}

В приведенном ниже примере ответа предложения включены результаты предложений для my-suggest-1 и my-suggest-2. Каждая часть предложения содержит записи. Каждая запись фактически является токеном из текста предложения и содержит текст предложения, исходный начальный смещение и длину в тексте предложения, и, при необходимости, произвольное количество вариантов.

{
  "_shards": ...
  "hits": ...
  "took": 2,
  "timed_out": false,
  "suggest": {
    "my-suggest-1": [ {
      "text": "tring",
      "offset": 0,
      "length": 5,
      "options": [ {"text": "trying", "score": 0.8, "freq": 1 } ]
    }, {
      "text": "out",
      "offset": 6,
      "length": 3,
      "options": []
    }, {
      "text": "elasticsearch",
      "offset": 10,
      "length": 13,
      "options": []
    } ],
    "my-suggest-2": ...
  }
}

Каждый массив вариантов содержит объект варианта, который включает предложенный текст, его частоту документов и рейтинг по сравнению с текстом предложения. Значение рейтинга зависит от используемого предложения. Рейтинг предложения по термину основывается на расстоянии редактирования.

Глобальный текст предложения

Чтобы избежать повторения текста предложения, можно определить глобальный текст. В примере ниже текст предложения определен глобально и применяется к предложениям my-suggest-1 и my-suggest-2.

$params = [
    'body' => [
        'suggest' => [
            'text' => 'tring out Elasticsearch',
            'my-suggest-1' => [
                'term' => [
                    'field' => 'message',
                ],
            ],
            'my-suggest-2' => [
                'term' => [
                    'field' => 'user',
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
resp = client.search(
    suggest={
        "text": "tring out Elasticsearch",
        "my-suggest-1": {
            "term": {
                "field": "message"
            }
        },
        "my-suggest-2": {
            "term": {
                "field": "user"
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    suggest: {
      text: 'tring out Elasticsearch',
      "my-suggest-1": {
        term: {
          field: 'message'
        }
      },
      "my-suggest-2": {
        term: {
          field: 'user'
        }
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithBody(strings.NewReader(`{
	  "suggest": {
	    "text": "tring out Elasticsearch",
	    "my-suggest-1": {
	      "term": {
	        "field": "message"
	      }
	    },
	    "my-suggest-2": {
	      "term": {
	        "field": "user"
	      }
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  suggest: {
    text: "tring out Elasticsearch",
    "my-suggest-1": {
      term: {
        field: "message",
      },
    },
    "my-suggest-2": {
      term: {
        field: "user",
      },
    },
  },
});
console.log(response);
POST _search
{
  "suggest": {
    "text" : "tring out Elasticsearch",
    "my-suggest-1" : {
      "term" : {
        "field" : "message"
      }
    },
    "my-suggest-2" : {
       "term" : {
        "field" : "user"
       }
    }
  }
}

В приведенном выше примере текст предложения также можно указать как вариант, специфичный для предложения. Текст предложения, указанный на уровне предложения, переопределяет текст предложения на глобальном уровне.

Предложение по термину

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

Общие параметры предложения:

text

Текст предложения. Текст предложения — это обязательный параметр, который необходимо задать глобально или на уровне предложения.

field

Поле для извлечения кандидатов предложений. Это обязательный параметр, который необходимо задать глобально или на уровне предложения.

analyzer

Анализатор для анализа текста предложения. По умолчанию используется анализатор поиска для поля предложения.

size

Максимальное количество исправлений, возвращаемых на каждый токен текста предложения.

sort

Определяет, как должны сортироваться предложения по каждому термину текста предложения. Два возможных значения:

  • score: Сначала сортировать по рейтингу, затем по частоте документов, а затем по самому термину.
  • frequency: Сначала сортировать по частоте документов, затем по рейтингу схожести, а затем по самому термину.

suggest_mode

Режим предложения управляет включением предложений или управляет тем, для каких терминов текста предложения должны быть предложены предложения. Три возможных значения:

  • missing: Предлагаются только предложения для терминов текста предложения, которых нет в индексе (по умолчанию).
  • popular: Предлагаются только предложения, которые встречаются в большем количестве документов, чем исходный термин текста предложения.
  • always: Предлагаются любые совпадающие предложения, основанные на терминах в тексте предложения.

Другие параметры предложения по термину:

max_edits

Максимальное расстояние редактирования, которое могут иметь кандидаты предложений, чтобы считаться предложением. Может принимать значение от 1 до 2. Любое другое значение приведет к ошибке плохого запроса. По умолчанию 2.

prefix_length

Количество минимальных символов префикса, которые должны совпадать, чтобы быть кандидатом для предложений. По умолчанию 1. Увеличение этого числа улучшает производительность проверки орфографии. Обычно ошибки в написании не встречаются в начале терминов.

min_word_length

Минимальная длина термина текста предложения, необходимая для включения. По умолчанию 4.

shard_size

Устанавливает максимальное количество предложений, извлекаемых с каждого отдельного фрагмента. Во время фазы сокращения возвращаются только лучшие N предложений на основе параметра size. По умолчанию параметр size. Установка этого значения выше параметра size может быть полезна для получения более точной частоты документов для исправления ошибок написания за счет производительности. Из-за того, что термины распределены по фрагментам, частоты документов на уровне фрагмента для исправления ошибок написания могут быть неточными. Увеличение этого значения сделает эти частоты документов более точными.

max_inspections

Фактор, используемый для умножения на shard_size, чтобы проверить больше кандидатов для исправления ошибок написания на уровне фрагмента. Может улучшить точность за счет производительности. По умолчанию 5.

min_doc_freq

Минимальный порог количества документов, в которых должно встречаться предложение. Это может быть задано как абсолютное число или как относительный процент от количества документов. Это может повысить качество, предлагая только термины с высокой частотой. По умолчанию 0f и не включено. Если задано значение больше 1, то число не может быть дробным. Частоты документов на уровне фрагмента используются для этого параметра.

max_term_freq

Максимальный порог количества документов, в которых может встречаться токен текста предложения, чтобы быть включенным. Может быть относительным процентным числом (например, 0,4) или абсолютным числом для представления частот документов. Если задано значение больше 1, дробные значения не допускаются. По умолчанию 0,01f. Это можно использовать для исключения терминов с высокой частотой — которые обычно написаны правильно — из проверки орфографии. Это также улучшает производительность проверки орфографии. Частоты документов на уровне фрагмента используются для этого параметра.

string_distance

Реализация алгоритма вычисления расстояния строк для сравнения схожести предложенных терминов. Пять возможных значений:

  • internal: По умолчанию, основанный на damerau_levenshtein, но сильно оптимизирован для сравнения расстояния строк для терминов в индексе.
  • damerau_levenshtein: Алгоритм расстояния строк на основе алгоритма Дамерау-Левенштейна.
  • levenshtein: Алгоритм расстояния строк на основе алгоритма Левенштейна.
  • jaro_winkler: Алгоритм расстояния строк на основе алгоритма Яро-Винклера.
  • ngram: Алгоритм расстояния строк на основе n-грамм символов.

Предлагатель фраз

Предлагатель term предоставляет очень удобный API для доступа к альтернативам слов на основе количества токенов в определённом расстоянии. API позволяет получить доступ к каждому токену в потоке, при этом выбор предложения оставляется потребителю API. Тем не менее, часто требуются предварительно выбранные предложения для представления пользователю. Предлагатель phrase добавляет дополнительную логику поверх предлагателя term для выбора целых исправленных фраз вместо отдельных токенов, взвешенных на основе моделей ngram-language. На практике этот предлагатель сможет принимать лучшие решения о выборе токенов на основе совместного появления и частот.

Пример API

В общем случае предлагатель phrase требует предварительного специального сопоставления для работы. Примеры предлагателя phrase на этой странице требуют следующего сопоставления для работы. Анализатор reverse используется только в последнем примере.

resp = client.indices.create(
    index="test",
    settings={
        "index": {
            "number_of_shards": 1,
            "analysis": {
                "analyzer": {
                    "trigram": {
                        "type": "custom",
                        "tokenizer": "standard",
                        "filter": [
                            "lowercase",
                            "shingle"
                        ]
                    },
                    "reverse": {
                        "type": "custom",
                        "tokenizer": "standard",
                        "filter": [
                            "lowercase",
                            "reverse"
                        ]
                    }
                },
                "filter": {
                    "shingle": {
                        "type": "shingle",
                        "min_shingle_size": 2,
                        "max_shingle_size": 3
                    }
                }
            }
        }
    },
    mappings={
        "properties": {
            "title": {
                "type": "text",
                "fields": {
                    "trigram": {
                        "type": "text",
                        "analyzer": "trigram"
                    },
                    "reverse": {
                        "type": "text",
                        "analyzer": "reverse"
                    }
                }
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="test",
    refresh=True,
    document={
        "title": "noble warriors"
    },
)
print(resp1)

resp2 = client.index(
    index="test",
    refresh=True,
    document={
        "title": "nobel prize"
    },
)
print(resp2)
response = client.indices.create(
  index: 'test',
  body: {
    settings: {
      index: {
        number_of_shards: 1,
        analysis: {
          analyzer: {
            trigram: {
              type: 'custom',
              tokenizer: 'standard',
              filter: [
                'lowercase',
                'shingle'
              ]
            },
            reverse: {
              type: 'custom',
              tokenizer: 'standard',
              filter: [
                'lowercase',
                'reverse'
              ]
            }
          },
          filter: {
            shingle: {
              type: 'shingle',
              min_shingle_size: 2,
              max_shingle_size: 3
            }
          }
        }
      }
    },
    mappings: {
      properties: {
        title: {
          type: 'text',
          fields: {
            trigram: {
              type: 'text',
              analyzer: 'trigram'
            },
            reverse: {
              type: 'text',
              analyzer: 'reverse'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'test',
  refresh: true,
  body: {
    title: 'noble warriors'
  }
)
puts response

response = client.index(
  index: 'test',
  refresh: true,
  body: {
    title: 'nobel prize'
  }
)
puts response
const response = await client.indices.create({
  index: "test",
  settings: {
    index: {
      number_of_shards: 1,
      analysis: {
        analyzer: {
          trigram: {
            type: "custom",
            tokenizer: "standard",
            filter: ["lowercase", "shingle"],
          },
          reverse: {
            type: "custom",
            tokenizer: "standard",
            filter: ["lowercase", "reverse"],
          },
        },
        filter: {
          shingle: {
            type: "shingle",
            min_shingle_size: 2,
            max_shingle_size: 3,
          },
        },
      },
    },
  },
  mappings: {
    properties: {
      title: {
        type: "text",
        fields: {
          trigram: {
            type: "text",
            analyzer: "trigram",
          },
          reverse: {
            type: "text",
            analyzer: "reverse",
          },
        },
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "test",
  refresh: "true",
  document: {
    title: "noble warriors",
  },
});
console.log(response1);

const response2 = await client.index({
  index: "test",
  refresh: "true",
  document: {
    title: "nobel prize",
  },
});
console.log(response2);
PUT test
{
  "settings": {
    "index": {
      "number_of_shards": 1,
      "analysis": {
        "analyzer": {
          "trigram": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": ["lowercase","shingle"]
          },
          "reverse": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": ["lowercase","reverse"]
          }
        },
        "filter": {
          "shingle": {
            "type": "shingle",
            "min_shingle_size": 2,
            "max_shingle_size": 3
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "fields": {
          "trigram": {
            "type": "text",
            "analyzer": "trigram"
          },
          "reverse": {
            "type": "text",
            "analyzer": "reverse"
          }
        }
      }
    }
  }
}
POST test/_doc?refresh=true
{"title": "noble warriors"}
POST test/_doc?refresh=true
{"title": "nobel prize"}

После настройки анализаторов и сопоставлений вы можете использовать предлагатель phrase в том же месте, где вы бы использовали предлагатель term:

resp = client.search(
    index="test",
    suggest={
        "text": "noble prize",
        "simple_phrase": {
            "phrase": {
                "field": "title.trigram",
                "size": 1,
                "gram_size": 3,
                "direct_generator": [
                    {
                        "field": "title.trigram",
                        "suggest_mode": "always"
                    }
                ],
                "highlight": {
                    "pre_tag": "<em>",
                    "post_tag": "</em>"
                }
            }
        }
    },
)
print(resp)
const response = await client.search({
  index: "test",
  suggest: {
    text: "noble prize",
    simple_phrase: {
      phrase: {
        field: "title.trigram",
        size: 1,
        gram_size: 3,
        direct_generator: [
          {
            field: "title.trigram",
            suggest_mode: "always",
          },
        ],
        highlight: {
          pre_tag: "<em>",
          post_tag: "</em>",
        },
      },
    },
  },
});
console.log(response);
POST test/_search
{
  "suggest": {
    "text": "noble prize",
    "simple_phrase": {
      "phrase": {
        "field": "title.trigram",
        "size": 1,
        "gram_size": 3,
        "direct_generator": [ {
          "field": "title.trigram",
          "suggest_mode": "always"
        } ],
        "highlight": {
          "pre_tag": "<em>",
          "post_tag": "</em>"
        }
      }
    }
  }
}

Ответ содержит предложения, отсортированные по наиболее вероятному исправлению орфографических ошибок. В данном случае мы получили ожидаемое исправление «нобелевская премия».

{
  "_shards": ...
  "hits": ...
  "timed_out": false,
  "took": 3,
  "suggest": {
    "simple_phrase" : [
      {
        "text" : "noble prize",
        "offset" : 0,
        "length" : 11,
        "options" : [ {
          "text" : "nobel prize",
          "highlighted": "<em>nobel</em> prize",
          "score" : 0.48614594
        }]
      }
    ]
  }
}

Основные параметры API для предложений фраз

field

Имя поля, используемого для поиска n-грамм в модели языка; предлагатель будет использовать это поле для получения статистических данных для оценки исправлений. Это поле является обязательным.

gram_size

Устанавливает максимальный размер n-грамм (шинглов) в field. Если поле не содержит n-грамм (шинглов), это следует опустить или установить на 1. Обратите внимание, что Elasticsearch пытается определить размер граммы на основе указанного field. Если поле использует фильтр shingle, gram_size устанавливается на max_shingle_size, если не указано явно.

real_word_error_likelihood

Вероятность того, что термин написан неправильно, даже если термин существует в словаре. По умолчанию значение 0.95, что означает, что 5% реальных слов написаны неправильно.

confidence

Уровень доверия определяет коэффициент, применяемый к результатам оценки входных фраз, который используется в качестве порога для других кандидатов на предложенные значения. В результат будут включены только кандидаты, набравшие больше очков, чем порог. Например, уровень доверия 1.0 вернёт только те предложения, которые набрали больше очков, чем исходная фраза. Если установлено значение 0.0, возвращаются лучшие N кандидатов. Значение по умолчанию - 1.0.

max_errors

Максимальный процент терминов, рассматриваемых как написанные неправильно, для формирования исправления. Этот метод принимает число с плавающей запятой в диапазоне [0..1) в качестве доли фактических терминов запроса или число >=1 в качестве абсолютного количества терминов запроса. По умолчанию установлено значение 1.0, что означает, что возвращаются только исправления с не более чем одним неправильно написанным термином. Обратите внимание, что установка слишком высокого значения может негативно повлиять на производительность. Рекомендуются низкие значения, например, 1 или 2; в противном случае время, затрачиваемое на вызовы suggest, может превысить время, затрачиваемое на выполнение запроса.

separator

Разделитель, используемый для разделения терминов в поле bigram. Если не указано, в качестве разделителя используется пробел.

size

Количество кандидатов, генерируемых для каждого отдельного термина запроса. Низкие числа, например, 3 или 5, обычно дают хорошие результаты. Увеличение этого значения может привести к появлению терминов с более высокой редактируемой дистанцией. Значение по умолчанию - 5.

analyzer

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

shard_size

Устанавливает максимальное количество предложенных терминов, которые будут извлекаться с каждого отдельного фрагмента. На этапе сворачивания возвращаются только лучшие N предложений на основе параметра size. Значение по умолчанию - 5.

text

Устанавливает текст/запрос для предоставления предложений.

highlight

Настройка выделения предложений. Если не задано, то поле highlighted не возвращается. Если указано, то должно содержать точно pre_tag и post_tag, которые обрамляют изменённые токены. Если несколько токенов подряд изменены, вся фраза изменённых токенов обрамляется, а не каждый токен.

collate

Проверяет каждое предложение на соответствие указанному query, чтобы исключить предложения, для которых в индексе нет соответствующих документов. Запрос сопоставления для предложения выполняется только на локальном фрагменте, из которого было сгенерировано предложение. query должен быть указан, и он может быть шаблонизирован. См. Шаблоны поиска. Текущее предложение автоматически становится доступным в качестве переменной {{suggestion}}, которую необходимо использовать в вашем запросе. Вы по-прежнему можете указать свой собственный шаблон params — значение suggestion будет добавлено к переменным, которые вы укажете. Кроме того, вы можете указать prune для управления тем, будут ли возвращаться все предложения фразы; при установке значения true предложения будут иметь дополнительный параметр collate_match, который будет true, если соответствующие документы для фразы были найдены, и false в противном случае. Значение по умолчанию для prune - false.

resp = client.search(
    index="test",
    suggest={
        "text": "noble prize",
        "simple_phrase": {
            "phrase": {
                "field": "title.trigram",
                "size": 1,
                "direct_generator": [
                    {
                        "field": "title.trigram",
                        "suggest_mode": "always",
                        "min_word_length": 1
                    }
                ],
                "collate": {
                    "query": {
                        "source": {
                            "match": {
                                "{{field_name}}": "{{suggestion}}"
                            }
                        }
                    },
                    "params": {
                        "field_name": "title"
                    },
                    "prune": True
                }
            }
        }
    },
)
print(resp)
const response = await client.search({
  index: "test",
  suggest: {
    text: "noble prize",
    simple_phrase: {
      phrase: {
        field: "title.trigram",
        size: 1,
        direct_generator: [
          {
            field: "title.trigram",
            suggest_mode: "always",
            min_word_length: 1,
          },
        ],
        collate: {
          query: {
            source: {
              match: {
                "{{field_name}}": "{{suggestion}}",
              },
            },
          },
          params: {
            field_name: "title",
          },
          prune: true,
        },
      },
    },
  },
});
console.log(response);
POST test/_search
{
  "suggest": {
    "text" : "noble prize",
    "simple_phrase" : {
      "phrase" : {
        "field" :  "title.trigram",
        "size" :   1,
        "direct_generator" : [ {
          "field" :            "title.trigram",
          "suggest_mode" :     "always",
          "min_word_length" :  1
        } ],
        "collate": {
          "query": { 
            "source" : {
              "match": {
                "{{field_name}}" : "{{suggestion}}" 
              }
            }
          },
          "params": {"field_name" : "title"}, 
          "prune": true 
        }
      }
    }
  }
}

Этот запрос будет выполнен один раз для каждого предложения.

Переменная {{suggestion}} будет заменена текстом каждого предложения.

Дополнительная переменная field_name была указана в params и используется запросом match.

Все предложения будут возвращены с дополнительным параметром collate_match, указывающим, соответствовала ли сгенерированная фраза какому-либо документу.

Модели сглаживания

Предлагатель phrase поддерживает несколько моделей сглаживания для балансировки весов между редкими граммами (граммы (шинглы) отсутствуют в индексе) и частыми граммами (встречаются хотя бы один раз в индексе). Модель сглаживания можно выбрать, установив параметр smoothing на одно из следующих значений. Каждая модель сглаживания поддерживает определённые свойства, которые можно настроить.

stupid_backoff

Простая модель backoff, которая отступает к моделям n-грамм более низкого порядка, если счёт более высокого порядка 0, и дисконтирует модель n-грамм более низкого порядка с постоянным коэффициентом. Значение по умолчанию discount - 0.4. Stupid Backoff - это модель по умолчанию.

laplace

Модель сглаживания, использующая аддитивное сглаживание, где к всем счётам добавляется постоянная величина (обычно 1.0 или меньше) для балансировки весов. Значение по умолчанию alpha - 0.5.

linear_interpolation

Модель сглаживания, которая вычисляет взвешенное среднее униграмм, биграмм и триграмм на основе весов (лямбда), предоставленных пользователем. Линейная интерполяция не имеет значений по умолчанию. Все параметры (trigram_lambda, bigram_lambda, unigram_lambda) должны быть указаны.

resp = client.search(
    index="test",
    suggest={
        "text": "obel prize",
        "simple_phrase": {
            "phrase": {
                "field": "title.trigram",
                "size": 1,
                "smoothing": {
                    "laplace": {
                        "alpha": 0.7
                    }
                }
            }
        }
    },
)
print(resp)
const response = await client.search({
  index: "test",
  suggest: {
    text: "obel prize",
    simple_phrase: {
      phrase: {
        field: "title.trigram",
        size: 1,
        smoothing: {
          laplace: {
            alpha: 0.7,
          },
        },
      },
    },
  },
});
console.log(response);
POST test/_search
{
  "suggest": {
    "text" : "obel prize",
    "simple_phrase" : {
      "phrase" : {
        "field" : "title.trigram",
        "size" : 1,
        "smoothing" : {
          "laplace" : {
            "alpha" : 0.7
          }
        }
      }
    }
  }
}

Генераторы кандидатов

Предлагатель phrase использует генераторы кандидатов для создания списка возможных терминов для каждого термина в данном тексте. Один генератор кандидатов похож на предлагатель term, вызываемый для каждого отдельного термина в тексте. Результаты работы генераторов затем оцениваются в сочетании с кандидатами от других терминов для кандидатов на подбор.

В настоящее время поддерживается только один тип генератора кандидатов — direct_generator. API Phrase suggest принимает список генераторов по ключу direct_generator; каждый из генераторов в списке вызывается для каждого термина в исходном тексте.

Прямые генераторы

Прямые генераторы поддерживают следующие параметры:

field

Поле для извлечения кандидатов из предложений. Это обязательный параметр, который должен быть задан либо глобально, либо для каждого предложения.

size

Максимальное количество исправлений, возвращаемых на каждый токен текста предложений.

suggest_mode

Режим предложений управляет тем, какие предложения включаются в предложения, сгенерированные на каждом фрагменте. Все значения, кроме always, можно рассматривать как оптимизацию для генерации меньшего количества предложений для проверки на каждом фрагменте и они не проверяются повторно при объединении предложений, сгенерированных на каждом фрагменте. Таким образом, missing сгенерирует предложения для терминов на фрагментах, которые их не содержат, даже если другие фрагменты их содержат. Их следует отфильтровать с помощью confidence. Возможны три значения:

  • missing: Генерировать предложения только для терминов, которые отсутствуют на фрагменте. Это значение по умолчанию.
  • popular: Предлагать только термины, которые встречаются в большем количестве документов на фрагменте, чем исходный термин.
  • always: Предложить все совпадающие предложения на основе терминов в тексте предложений.

max_edits

Максимальное расстояние редактирования, которое могут иметь кандидаты на предложения, чтобы рассматриваться как предложение. Может принимать значения от 1 до 2. Любое другое значение приводит к ошибке «плохой запрос». Значение по умолчанию — 2.

prefix_length

Минимальное количество символов префикса, которые должны совпадать, чтобы считаться кандидатом на предложение. Значение по умолчанию — 1. Увеличение этого значения улучшает производительность проверки орфографии. Обычно опечатки не встречаются в начале терминов.

min_word_length

Минимальная длина термина текста предложений, необходимая для включения. Значение по умолчанию — 4.

max_inspections

Коэффициент, который используется для умножения на shard_size, чтобы проверить больше кандидатов на исправление орфографических ошибок на уровне фрагмента. Может повысить точность за счет производительности. Значение по умолчанию — 5.

min_doc_freq

Минимальный порог количества документов, в которых должно появляться предложение. Это может быть задано как абсолютное число или как относительный процент от количества документов. Это может повысить качество, предлагая только термины с высокой частотой. Значение по умолчанию — 0f и отключено. Если задано значение больше 1, оно не может быть дробным. Для этого параметра используются частоты документов на уровне фрагмента.

max_term_freq

Максимальный порог количества документов, в которых может присутствовать токен текста предложения, для включения. Может быть относительным процентным числом (например, 0,4) или абсолютным числом для представления частот документов. Если задано значение больше 1, то дробное значение не может быть задано. Значение по умолчанию — 0,01f. Это может использоваться для исключения терминов с высокой частотой (которые, как правило, написаны правильно) из проверки орфографии. Это также улучшает производительность проверки орфографии. Для этого параметра используются частоты документов на уровне фрагмента.

pre_filter

Фильтр (анализатор), применяемый к каждому из токенов, переданных этому генератору кандидатов. Этот фильтр применяется к исходному токену перед генерацией кандидатов.

post_filter

Фильтр (анализатор), который применяется к каждому из сгенерированных токенов перед передачей их фактическому оценщику фраз.

Следующий пример показывает вызов предложить phrase с двумя генераторами: первый использует поле, содержащее обычные индексированные термины, а второй использует поле, в котором используются термины, индексированные с помощью reverse фильтра (токены индексируются в обратном порядке). Это используется для преодоления ограничения прямых генераторов, требующих постоянного префикса для предоставления высокопроизводительных предложений. Параметры pre_filter и post_filter принимают обычные имена анализаторов.

resp = client.search(
    index="test",
    suggest={
        "text": "obel prize",
        "simple_phrase": {
            "phrase": {
                "field": "title.trigram",
                "size": 1,
                "direct_generator": [
                    {
                        "field": "title.trigram",
                        "suggest_mode": "always"
                    },
                    {
                        "field": "title.reverse",
                        "suggest_mode": "always",
                        "pre_filter": "reverse",
                        "post_filter": "reverse"
                    }
                ]
            }
        }
    },
)
print(resp)
const response = await client.search({
  index: "test",
  suggest: {
    text: "obel prize",
    simple_phrase: {
      phrase: {
        field: "title.trigram",
        size: 1,
        direct_generator: [
          {
            field: "title.trigram",
            suggest_mode: "always",
          },
          {
            field: "title.reverse",
            suggest_mode: "always",
            pre_filter: "reverse",
            post_filter: "reverse",
          },
        ],
      },
    },
  },
});
console.log(response);
POST test/_search
{
  "suggest": {
    "text" : "obel prize",
    "simple_phrase" : {
      "phrase" : {
        "field" : "title.trigram",
        "size" : 1,
        "direct_generator" : [ {
          "field" : "title.trigram",
          "suggest_mode" : "always"
        }, {
          "field" : "title.reverse",
          "suggest_mode" : "always",
          "pre_filter" : "reverse",
          "post_filter" : "reverse"
        } ]
      }
    }
  }
}

pre_filter и post_filter также могут быть использованы для вставки синонимов после генерации кандидатов. Например, для запроса captain usq мы можем сгенерировать кандидата usa для термина usq, который является синонимом america. Это позволяет нам представить captain america пользователю, если эта фраза наберет достаточно очков.

Предлагатель завершения

Предлагатель completion предоставляет функциональность автозаполнения/поиска по мере ввода. Это навигационная функция, которая помогает пользователям переходить к соответствующим результатам по мере ввода, повышая точность поиска. Это не предназначено для исправления орфографических ошибок или функции «Вы имели в виду…» (как у предлагателей term или phrase).

В идеале, функциональность автозаполнения должна быть такой же быстрой, как ввод текста пользователя, чтобы предоставлять мгновенную обратную связь, соответствующую тому, что пользователь уже ввел. Поэтому предлагатель completion оптимизирован для скорости. Предлагатель использует структуры данных, которые позволяют выполнять быстрый поиск, но стоят дорого для создания и хранятся в оперативной памяти.

Сопоставление

Для использования предлагателя completion, сопоставьте поле, из которого вы хотите генерировать предложения, как тип completion. Это индексирует значения поля для быстрого автозаполнения.

resp = client.indices.create(
    index="music",
    mappings={
        "properties": {
            "suggest": {
                "type": "completion"
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'music',
  body: {
    mappings: {
      properties: {
        suggest: {
          type: 'completion'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "music",
  mappings: {
    properties: {
      suggest: {
        type: "completion",
      },
    },
  },
});
console.log(response);
PUT music
{
  "mappings": {
    "properties": {
      "suggest": {
        "type": "completion"
      }
    }
  }
}

Параметры для completion полей

Следующие параметры принимаются completion полями:

analyzer

Используемый анализатор индекса, по умолчанию simple.

search_analyzer

Используемый анализатор поиска, по умолчанию значение analyzer.

preserve_separators

Сохраняет разделители, по умолчанию true. Если отключено, вы можете найти поле, начинающееся с Foo Fighters, если вы предложите для foof.

preserve_position_increments

Включает приращения позиций, по умолчанию true. Если отключено и используется анализатор стоп-слов, вы можете получить поле, начинающееся с The Beatles, если вы предложите для b.

Примечание
: Это можно также сделать, проиндексировав два входа, Beatles и The Beatles, не изменяя простой анализатор, если вы можете обогатить свои данные.

max_input_length

Ограничивает длину одного входа, по умолчанию 50 точек кода UTF-16. Это ограничение используется только во время индексирования для сокращения общего количества символов на строку ввода, чтобы предотвратить раздувание подлежащей структуре данных большими входами. В большинстве случаев значение по умолчанию не повлияет, так как префиксные завершения редко растут до префиксов, длина которых превышает несколько символов.

Индексирование

Вы индексируете предложения, как и любое другое поле. Предложение состоит из input и необязательного атрибута weight. input — ожидаемый текст, который должен быть сопоставлен запросом на предложение, а weight определяет, как будут оцениваться предложения. Индексирование предложения выполняется следующим образом:

resp = client.index(
    index="music",
    id="1",
    refresh=True,
    document={
        "suggest": {
            "input": [
                "Nevermind",
                "Nirvana"
            ],
            "weight": 34
        }
    },
)
print(resp)
response = client.index(
  index: 'music',
  id: 1,
  refresh: true,
  body: {
    suggest: {
      input: [
        'Nevermind',
        'Nirvana'
      ],
      weight: 34
    }
  }
)
puts response
const response = await client.index({
  index: "music",
  id: 1,
  refresh: "true",
  document: {
    suggest: {
      input: ["Nevermind", "Nirvana"],
      weight: 34,
    },
  },
});
console.log(response);
PUT music/_doc/1?refresh
{
  "suggest" : {
    "input": [ "Nevermind", "Nirvana" ],
    "weight" : 34
  }
}

Поддерживаются следующие параметры:

input

Вводимые данные для хранения, это может быть массив строк или просто строка. Это обязательное поле.

Это значение не может содержать следующие управляющие символы UTF-16:

  • \u0000 (null)
  • \u001f (разделитель информации один)
  • \u001e (разделитель информации два)

weight

Положительное целое число или строка, содержащая положительное целое число, которое определяет вес и позволяет вам ранжировать ваши предложения. Это необязательное поле.

Вы можете проиндексировать несколько предложений для документа следующим образом:

resp = client.index(
    index="music",
    id="1",
    refresh=True,
    document={
        "suggest": [
            {
                "input": "Nevermind",
                "weight": 10
            },
            {
                "input": "Nirvana",
                "weight": 3
            }
        ]
    },
)
print(resp)
response = client.index(
  index: 'music',
  id: 1,
  refresh: true,
  body: {
    suggest: [
      {
        input: 'Nevermind',
        weight: 10
      },
      {
        input: 'Nirvana',
        weight: 3
      }
    ]
  }
)
puts response
const response = await client.index({
  index: "music",
  id: 1,
  refresh: "true",
  document: {
    suggest: [
      {
        input: "Nevermind",
        weight: 10,
      },
      {
        input: "Nirvana",
        weight: 3,
      },
    ],
  },
});
console.log(response);
PUT music/_doc/1?refresh
{
  "suggest": [
    {
      "input": "Nevermind",
      "weight": 10
    },
    {
      "input": "Nirvana",
      "weight": 3
    }
  ]
}

Вы можете использовать следующий сокращенный формат. Обратите внимание, что вы не можете указать вес с suggestion(s) в сокращенной форме.

resp = client.index(
    index="music",
    id="1",
    refresh=True,
    document={
        "suggest": [
            "Nevermind",
            "Nirvana"
        ]
    },
)
print(resp)
response = client.index(
  index: 'music',
  id: 1,
  refresh: true,
  body: {
    suggest: [
      'Nevermind',
      'Nirvana'
    ]
  }
)
puts response
const response = await client.index({
  index: "music",
  id: 1,
  refresh: "true",
  document: {
    suggest: ["Nevermind", "Nirvana"],
  },
});
console.log(response);
PUT music/_doc/1?refresh
{
  "suggest" : [ "Nevermind", "Nirvana" ]
}

Запрос

Предложение работает как обычно, за исключением того, что вам нужно указать тип предложения как completion. Предложения находятся в режиме реального времени, что означает, что новые предложения могут быть отображены с помощью обновления, а удаленные документы никогда не отображаются. Этот запрос:

resp = client.search(
    index="music",
    pretty=True,
    suggest={
        "song-suggest": {
            "prefix": "nir",
            "completion": {
                "field": "suggest"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'music',
  pretty: true,
  body: {
    suggest: {
      "song-suggest": {
        prefix: 'nir',
        completion: {
          field: 'suggest'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "music",
  pretty: "true",
  suggest: {
    "song-suggest": {
      prefix: "nir",
      completion: {
        field: "suggest",
      },
    },
  },
});
console.log(response);
POST music/_search?pretty
{
  "suggest": {
    "song-suggest": {
      "prefix": "nir",        
      "completion": {         
          "field": "suggest"  
      }
    }
  }
}

Префикс, используемый для поиска предложений

Тип предложений

Имя поля для поиска предложений

возвращает такой ответ:

{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits": ...
  "took": 2,
  "timed_out": false,
  "suggest": {
    "song-suggest" : [ {
      "text" : "nir",
      "offset" : 0,
      "length" : 3,
      "options" : [ {
        "text" : "Nirvana",
        "_index": "music",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "suggest": ["Nevermind", "Nirvana"]
        }
      } ]
    } ]
  }
}

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

Назначенный вес предложения возвращается как _score. text поле использует input вашего индексированного предложения. Предложения возвращают весь документ _source по умолчанию. Размер _source может влиять на производительность из-за доступа к диску и сетевой передаче. Чтобы сохранить сетевую нагрузку, отфильтруйте нежелательные поля из _source, используя фильтрацию источника, чтобы минимизировать размер _source. Обратите внимание, что конечная точка _suggest не поддерживает фильтрацию источника, но использование suggest на _search конечной точке поддерживает:

resp = client.search(
    index="music",
    source="suggest",
    suggest={
        "song-suggest": {
            "prefix": "nir",
            "completion": {
                "field": "suggest",
                "size": 5
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'music',
  body: {
    _source: 'suggest',
    suggest: {
      "song-suggest": {
        prefix: 'nir',
        completion: {
          field: 'suggest',
          size: 5
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "music",
  _source: "suggest",
  suggest: {
    "song-suggest": {
      prefix: "nir",
      completion: {
        field: "suggest",
        size: 5,
      },
    },
  },
});
console.log(response);
POST music/_search
{
  "_source": "suggest",     
  "suggest": {
    "song-suggest": {
      "prefix": "nir",
      "completion": {
        "field": "suggest", 
        "size": 5           
      }
    }
  }
}

Отфильтровать источник, чтобы вернуть только поле suggest

Имя поля для поиска предложений

Количество предложений для возврата

Что должно выглядеть так:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "suggest": {
    "song-suggest": [ {
        "text": "nir",
        "offset": 0,
        "length": 3,
        "options": [ {
            "text": "Nirvana",
            "_index": "music",
            "_id": "1",
            "_score": 1.0,
            "_source": {
              "suggest": [ "Nevermind", "Nirvana" ]
            }
          } ]
      } ]
  }
}

Запрос базового подсказывателя завершения поддерживает следующие параметры:

field

Имя поля, на котором нужно выполнить запрос (обязательно).

size

Количество предложений для возврата (по умолчанию 5).

skip_duplicates

Нужно ли отфильтровывать дубликаты предложений (по умолчанию false).

Подсказыватель завершения рассматривает все документы в индексе. См. Подсказыватель контекста для объяснения того, как запросить подмножество документов вместо этого.

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

Пропуск дубликатов предложений

Запросы могут возвращать дублированные предложения, поступающие из разных документов. Можно изменить это поведение, установив skip_duplicates в значение true. При установке этого параметра от результатов отфильтровываются документы с дублированными предложениями.

resp = client.search(
    index="music",
    pretty=True,
    suggest={
        "song-suggest": {
            "prefix": "nor",
            "completion": {
                "field": "suggest",
                "skip_duplicates": True
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'music',
  pretty: true,
  body: {
    suggest: {
      "song-suggest": {
        prefix: 'nor',
        completion: {
          field: 'suggest',
          skip_duplicates: true
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "music",
  pretty: "true",
  suggest: {
    "song-suggest": {
      prefix: "nor",
      completion: {
        field: "suggest",
        skip_duplicates: true,
      },
    },
  },
});
console.log(response);
POST music/_search?pretty
{
  "suggest": {
    "song-suggest": {
      "prefix": "nor",
      "completion": {
        "field": "suggest",
        "skip_duplicates": true
      }
    }
  }
}

При установке в значение true этот параметр может замедлить поиск, так как для нахождения N лучших предложений необходимо посетить больше предложений.

Нечёткие запросы

Предлагатель завершения также поддерживает нечёткие запросы — это означает, что вы можете иметь опечатку в своём поиске и всё равно получить результаты.

resp = client.search(
    index="music",
    pretty=True,
    suggest={
        "song-suggest": {
            "prefix": "nor",
            "completion": {
                "field": "suggest",
                "fuzzy": {
                    "fuzziness": 2
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'music',
  pretty: true,
  body: {
    suggest: {
      "song-suggest": {
        prefix: 'nor',
        completion: {
          field: 'suggest',
          fuzzy: {
            fuzziness: 2
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "music",
  pretty: "true",
  suggest: {
    "song-suggest": {
      prefix: "nor",
      completion: {
        field: "suggest",
        fuzzy: {
          fuzziness: 2,
        },
      },
    },
  },
});
console.log(response);
POST music/_search?pretty
{
  "suggest": {
    "song-suggest": {
      "prefix": "nor",
      "completion": {
        "field": "suggest",
        "fuzzy": {
          "fuzziness": 2
        }
      }
    }
  }
}

Предложения, которые разделяют наибольший префикс с запросом prefix, будут иметь более высокий рейтинг.

Нечёткий запрос может принимать определённые параметры нечёткости. Поддерживаются следующие параметры:

fuzziness

Фактор нечёткости, по умолчанию равен AUTO. Смотрите Нечёткость для разрешённых настроек.

transpositions

Если установлено значение true, транспозиции считаются одной заменой вместо двух, по умолчанию true

min_length

Минимальная длина входных данных перед возвращением нечёткой подборки, по умолчанию 3

prefix_length

Минимальная длина входных данных, которая не проверяется на нечёткое соответствие, по умолчанию 1

unicode_aware

Если true, все измерения (например, нечёткое расстояние редактирования, транспозиции и длины) измеряются в кодовых точках Юникода, а не в байтах. Это немного медленнее, чем сырые байты, поэтому по умолчанию установлено значение false.

Если вы хотите придерживаться значений по умолчанию, но всё равно использовать нечёткость, вы можете либо использовать fuzzy: {}, либо fuzzy: true.

Запросы с использованием регулярных выражений

Предлагатель завершения также поддерживает запросы с регулярными выражениями, что означает, что вы можете выразить префикс как регулярное выражение.

resp = client.search(
    index="music",
    pretty=True,
    suggest={
        "song-suggest": {
            "regex": "n[ever|i]r",
            "completion": {
                "field": "suggest"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'music',
  pretty: true,
  body: {
    suggest: {
      "song-suggest": {
        regex: 'n[ever|i]r',
        completion: {
          field: 'suggest'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "music",
  pretty: "true",
  suggest: {
    "song-suggest": {
      regex: "n[ever|i]r",
      completion: {
        field: "suggest",
      },
    },
  },
});
console.log(response);
POST music/_search?pretty
{
  "suggest": {
    "song-suggest": {
      "regex": "n[ever|i]r",
      "completion": {
        "field": "suggest"
      }
    }
  }
}

Запрос с регулярным выражением может принимать определённые параметры регулярных выражений. Поддерживаются следующие параметры:

flags

Возможные флаги — ALL (по умолчанию), ANYSTRING, COMPLEMENT, EMPTY, INTERSECTION, INTERVAL или NONE. Смотрите regexp-syntax для их значения.

max_determinized_states

Регулярные выражения опасны, потому что легко случайно создать безобидный на вид запрос, для выполнения которого Lucene требует экспоненциального числа внутренних состояний детерминированного автомата (и соответствующей оперативной памяти и ЦП). Lucene предотвращает это, используя настройку max_determinized_states (по умолчанию 10000). Вы можете увеличить этот лимит, чтобы разрешить выполнение более сложных регулярных выражений.

Предлагатель контекста

Предлагатель завершения учитывает все документы в индексе, но часто желательно предоставлять предложения, отфильтрованные и/или усиленные по определенным критериям. Например, вы хотите предложить названия песен, отфильтрованные по определенным исполнителям, или усилить названия песен на основе их жанра.

Для достижения фильтрации и/или усиления предложений вы можете добавить соответствия контекста при конфигурации поля завершения. Вы можете определить несколько соответствий контекста для одного поля завершения. Каждое соответствие контекста имеет уникальное имя и тип. Существуют два типа: category и geo. Соответствия контекста настраиваются в параметре contexts в отображении поля.

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

Максимальное количество допустимых соответствий контекста поля завершения — 10.

Ниже определены типы, каждый с двумя соответствиями контекста для поля завершения:

resp = client.indices.create(
    index="place",
    mappings={
        "properties": {
            "suggest": {
                "type": "completion",
                "contexts": [
                    {
                        "name": "place_type",
                        "type": "category"
                    },
                    {
                        "name": "location",
                        "type": "geo",
                        "precision": 4
                    }
                ]
            }
        }
    },
)
print(resp)

resp1 = client.indices.create(
    index="place_path_category",
    mappings={
        "properties": {
            "suggest": {
                "type": "completion",
                "contexts": [
                    {
                        "name": "place_type",
                        "type": "category",
                        "path": "cat"
                    },
                    {
                        "name": "location",
                        "type": "geo",
                        "precision": 4,
                        "path": "loc"
                    }
                ]
            },
            "loc": {
                "type": "geo_point"
            }
        }
    },
)
print(resp1)
response = client.indices.create(
  index: 'place',
  body: {
    mappings: {
      properties: {
        suggest: {
          type: 'completion',
          contexts: [
            {
              name: 'place_type',
              type: 'category'
            },
            {
              name: 'location',
              type: 'geo',
              precision: 4
            }
          ]
        }
      }
    }
  }
)
puts response

response = client.indices.create(
  index: 'place_path_category',
  body: {
    mappings: {
      properties: {
        suggest: {
          type: 'completion',
          contexts: [
            {
              name: 'place_type',
              type: 'category',
              path: 'cat'
            },
            {
              name: 'location',
              type: 'geo',
              precision: 4,
              path: 'loc'
            }
          ]
        },
        loc: {
          type: 'geo_point'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "place",
  mappings: {
    properties: {
      suggest: {
        type: "completion",
        contexts: [
          {
            name: "place_type",
            type: "category",
          },
          {
            name: "location",
            type: "geo",
            precision: 4,
          },
        ],
      },
    },
  },
});
console.log(response);

const response1 = await client.indices.create({
  index: "place_path_category",
  mappings: {
    properties: {
      suggest: {
        type: "completion",
        contexts: [
          {
            name: "place_type",
            type: "category",
            path: "cat",
          },
          {
            name: "location",
            type: "geo",
            precision: 4,
            path: "loc",
          },
        ],
      },
      loc: {
        type: "geo_point",
      },
    },
  },
});
console.log(response1);
PUT place
{
  "mappings": {
    "properties": {
      "suggest": {
        "type": "completion",
        "contexts": [
          {                                 
            "name": "place_type",
            "type": "category"
          },
          {                                 
            "name": "location",
            "type": "geo",
            "precision": 4
          }
        ]
      }
    }
  }
}
PUT place_path_category
{
  "mappings": {
    "properties": {
      "suggest": {
        "type": "completion",
        "contexts": [
          {                           
            "name": "place_type",
            "type": "category",
            "path": "cat"
          },
          {                           
            "name": "location",
            "type": "geo",
            "precision": 4,
            "path": "loc"
          }
        ]
      },
      "loc": {
        "type": "geo_point"
      }
    }
  }
}

Определяет контекст category с именем place_type, где категории должны быть отправлены вместе с предложениями.

Определяет контекст geo с именем location, где категории должны быть отправлены вместе с предложениями.

Определяет контекст category с именем place_type, где категории считываются из поля cat.

Определяет контекст geo с именем location, где категории считываются из поля loc.

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

Контекст категорий

Контекст category позволяет связать одну или несколько категорий с предложениями во время индексирования. Во время запроса предложения могут быть отфильтрованы и усилены по их связанным категориям.

Сопоставления настраиваются так же, как и поля place_type выше. Если path определено, то категории считываются из этого пути в документе, в противном случае они должны быть отправлены в поле suggest следующим образом:

resp = client.index(
    index="place",
    id="1",
    document={
        "suggest": {
            "input": [
                "timmy's",
                "starbucks",
                "dunkin donuts"
            ],
            "contexts": {
                "place_type": [
                    "cafe",
                    "food"
                ]
            }
        }
    },
)
print(resp)
response = client.index(
  index: 'place',
  id: 1,
  body: {
    suggest: {
      input: [
        "timmy's",
        'starbucks',
        'dunkin donuts'
      ],
      contexts: {
        place_type: [
          'cafe',
          'food'
        ]
      }
    }
  }
)
puts response
const response = await client.index({
  index: "place",
  id: 1,
  document: {
    suggest: {
      input: ["timmy's", "starbucks", "dunkin donuts"],
      contexts: {
        place_type: ["cafe", "food"],
      },
    },
  },
});
console.log(response);
PUT place/_doc/1
{
  "suggest": {
    "input": [ "timmy's", "starbucks", "dunkin donuts" ],
    "contexts": {
      "place_type": [ "cafe", "food" ]                    
    }
  }
}

Эти предложения будут связаны с категорией cafe и food.

Если для соответствия была определена path, то для добавления категорий достаточно следующего запроса к индексу:

resp = client.index(
    index="place_path_category",
    id="1",
    document={
        "suggest": [
            "timmy's",
            "starbucks",
            "dunkin donuts"
        ],
        "cat": [
            "cafe",
            "food"
        ]
    },
)
print(resp)
response = client.index(
  index: 'place_path_category',
  id: 1,
  body: {
    suggest: [
      "timmy's",
      'starbucks',
      'dunkin donuts'
    ],
    cat: [
      'cafe',
      'food'
    ]
  }
)
puts response
const response = await client.index({
  index: "place_path_category",
  id: 1,
  document: {
    suggest: ["timmy's", "starbucks", "dunkin donuts"],
    cat: ["cafe", "food"],
  },
});
console.log(response);
PUT place_path_category/_doc/1
{
  "suggest": ["timmy's", "starbucks", "dunkin donuts"],
  "cat": ["cafe", "food"] 
}

Эти предложения будут связаны с категорией cafe и food.

Если соответствие контекста ссылается на другое поле, а категории явно проиндексированы, предложения индексируются с обоими наборами категорий.

Запрос по категориям

Предложения могут быть отфильтрованы по одной или нескольким категориям. Следующий запрос фильтрует предложения по нескольким категориям:

resp = client.search(
    index="place",
    pretty=True,
    suggest={
        "place_suggestion": {
            "prefix": "tim",
            "completion": {
                "field": "suggest",
                "size": 10,
                "contexts": {
                    "place_type": [
                        "cafe",
                        "restaurants"
                    ]
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'place',
  pretty: true,
  body: {
    suggest: {
      place_suggestion: {
        prefix: 'tim',
        completion: {
          field: 'suggest',
          size: 10,
          contexts: {
            place_type: [
              'cafe',
              'restaurants'
            ]
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "place",
  pretty: "true",
  suggest: {
    place_suggestion: {
      prefix: "tim",
      completion: {
        field: "suggest",
        size: 10,
        contexts: {
          place_type: ["cafe", "restaurants"],
        },
      },
    },
  },
});
console.log(response);
POST place/_search?pretty
{
  "suggest": {
    "place_suggestion": {
      "prefix": "tim",
      "completion": {
        "field": "suggest",
        "size": 10,
        "contexts": {
          "place_type": [ "cafe", "restaurants" ]
        }
      }
    }
  }
}

Если в запросе установлены несколько категорий или контекстов категорий, они объединяются как дизъюнкция. Это означает, что предложения соответствуют, если они содержат хотя бы одно из предоставленных значений контекста.

Предложения с определенными категориями могут быть повыше, чем другие. Следующий запрос фильтрует предложения по категориям и дополнительно повышает предложения, связанные с определенными категориями:

resp = client.search(
    index="place",
    pretty=True,
    suggest={
        "place_suggestion": {
            "prefix": "tim",
            "completion": {
                "field": "suggest",
                "size": 10,
                "contexts": {
                    "place_type": [
                        {
                            "context": "cafe"
                        },
                        {
                            "context": "restaurants",
                            "boost": 2
                        }
                    ]
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'place',
  pretty: true,
  body: {
    suggest: {
      place_suggestion: {
        prefix: 'tim',
        completion: {
          field: 'suggest',
          size: 10,
          contexts: {
            place_type: [
              {
                context: 'cafe'
              },
              {
                context: 'restaurants',
                boost: 2
              }
            ]
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "place",
  pretty: "true",
  suggest: {
    place_suggestion: {
      prefix: "tim",
      completion: {
        field: "suggest",
        size: 10,
        contexts: {
          place_type: [
            {
              context: "cafe",
            },
            {
              context: "restaurants",
              boost: 2,
            },
          ],
        },
      },
    },
  },
});
console.log(response);
POST place/_search?pretty
{
  "suggest": {
    "place_suggestion": {
      "prefix": "tim",
      "completion": {
        "field": "suggest",
        "size": 10,
        "contexts": {
          "place_type": [                             
            { "context": "cafe" },
            { "context": "restaurants", "boost": 2 }
          ]
        }
      }
    }
  }
}

Запрос контекста фильтрует предложения, связанные с категориями cafe и restaurants, и повышает предложения, связанные с restaurants, на коэффициент 2.

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

context

Значение категории, по которой необходимо фильтровать/усиливать. Обязательно.

boost

Коэффициент, на который необходимо усилить рейтинг предложения. Рейтинг вычисляется путем умножения коэффициента усиления на вес предложения. По умолчанию — 1.

prefix

Необходимо ли рассматривать значение категории как префикс. Например, если установлено true, вы можете фильтровать категории type1, type2 и т. д., указав префикс категории type. По умолчанию — false.

Если предложение соответствует нескольким контекстам, итоговый рейтинг вычисляется как максимальный рейтинг, полученный по всем соответствующим контекстам.

Контекст геолокации

Контекст geo позволяет связать одно или несколько гео-точек или геохешей с предложениями во время индексирования. Во время запроса предложения могут быть отфильтрованы и усилены, если они находятся в определенном радиусе от указанной геолокации.

Внутренне гео-точки кодируются как геохеши с указанной точностью.

Гео-сопоставление

В дополнение к настройке path, соответствие контекста geo принимает следующие настройки:

precision

Это определяет точность геохеша, который должен быть проиндексирован, и может быть указан как значение расстояния (5m, 10km и т. д.) или как прямая точность геохеша (1..12). По умолчанию используется значение точности геохеша 6.

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

Индексирование гео-контекстов

Контексты geo могут быть явно заданы для предложений или проиндексированы из поля гео-точки документа с помощью параметра path, аналогично контекстам category. Связывание нескольких контекстов гео-локации с предложением проиндексирует это предложение для каждой гео-локации. В следующем примере индексируется предложение с двумя контекстами гео-локации:

resp = client.index(
    index="place",
    id="1",
    document={
        "suggest": {
            "input": "timmy's",
            "contexts": {
                "location": [
                    {
                        "lat": 43.6624803,
                        "lon": -79.3863353
                    },
                    {
                        "lat": 43.6624718,
                        "lon": -79.3873227
                    }
                ]
            }
        }
    },
)
print(resp)
response = client.index(
  index: 'place',
  id: 1,
  body: {
    suggest: {
      input: "timmy's",
      contexts: {
        location: [
          {
            lat: 43.6624803,
            lon: -79.3863353
          },
          {
            lat: 43.6624718,
            lon: -79.3873227
          }
        ]
      }
    }
  }
)
puts response
const response = await client.index({
  index: "place",
  id: 1,
  document: {
    suggest: {
      input: "timmy's",
      contexts: {
        location: [
          {
            lat: 43.6624803,
            lon: -79.3863353,
          },
          {
            lat: 43.6624718,
            lon: -79.3873227,
          },
        ],
      },
    },
  },
});
console.log(response);
PUT place/_doc/1
{
  "suggest": {
    "input": "timmy's",
    "contexts": {
      "location": [
        {
          "lat": 43.6624803,
          "lon": -79.3863353
        },
        {
          "lat": 43.6624718,
          "lon": -79.3873227
        }
      ]
    }
  }
}
Запрос геолокации

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

resp = client.search(
    index="place",
    suggest={
        "place_suggestion": {
            "prefix": "tim",
            "completion": {
                "field": "suggest",
                "size": 10,
                "contexts": {
                    "location": {
                        "lat": 43.662,
                        "lon": -79.38
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'place',
  body: {
    suggest: {
      place_suggestion: {
        prefix: 'tim',
        completion: {
          field: 'suggest',
          size: 10,
          contexts: {
            location: {
              lat: 43.662,
              lon: -79.38
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "place",
  suggest: {
    place_suggestion: {
      prefix: "tim",
      completion: {
        field: "suggest",
        size: 10,
        contexts: {
          location: {
            lat: 43.662,
            lon: -79.38,
          },
        },
      },
    },
  },
});
console.log(response);
POST place/_search
{
  "suggest": {
    "place_suggestion": {
      "prefix": "tim",
      "completion": {
        "field": "suggest",
        "size": 10,
        "contexts": {
          "location": {
            "lat": 43.662,
            "lon": -79.380
          }
        }
      }
    }
  }
}

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

Если в запросе установлены несколько категорий или контекстов категорий, они объединяются как дизъюнкция. Это означает, что предложения соответствуют, если они содержат хотя бы одно из предоставленных значений контекста.

Предложения, которые находятся в области, представленной геохешем, также могут быть усилены, как показано ниже:

resp = client.search(
    index="place",
    pretty=True,
    suggest={
        "place_suggestion": {
            "prefix": "tim",
            "completion": {
                "field": "suggest",
                "size": 10,
                "contexts": {
                    "location": [
                        {
                            "lat": 43.6624803,
                            "lon": -79.3863353,
                            "precision": 2
                        },
                        {
                            "context": {
                                "lat": 43.6624803,
                                "lon": -79.3863353
                            },
                            "boost": 2
                        }
                    ]
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'place',
  pretty: true,
  body: {
    suggest: {
      place_suggestion: {
        prefix: 'tim',
        completion: {
          field: 'suggest',
          size: 10,
          contexts: {
            location: [
              {
                lat: 43.6624803,
                lon: -79.3863353,
                precision: 2
              },
              {
                context: {
                  lat: 43.6624803,
                  lon: -79.3863353
                },
                boost: 2
              }
            ]
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "place",
  pretty: "true",
  suggest: {
    place_suggestion: {
      prefix: "tim",
      completion: {
        field: "suggest",
        size: 10,
        contexts: {
          location: [
            {
              lat: 43.6624803,
              lon: -79.3863353,
              precision: 2,
            },
            {
              context: {
                lat: 43.6624803,
                lon: -79.3863353,
              },
              boost: 2,
            },
          ],
        },
      },
    },
  },
});
console.log(response);
POST place/_search?pretty
{
  "suggest": {
    "place_suggestion": {
      "prefix": "tim",
      "completion": {
        "field": "suggest",
        "size": 10,
        "contexts": {
          "location": [             
                      {
              "lat": 43.6624803,
              "lon": -79.3863353,
              "precision": 2
            },
            {
              "context": {
                "lat": 43.6624803,
                "lon": -79.3863353
              },
              "boost": 2
            }
          ]
        }
      }
    }
  }
}

Запрос контекста фильтрует предложения, которые попадают под географическое положение, представленное геохешем (43.662, -79.380) с точностью 2, и усиливает предложения, которые попадают под представление геохеша (43.6624803, -79.3863353) с точностью по умолчанию 6, в 2 раз.

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

Помимо принятия значений контекста, запрос контекста может быть составлен из нескольких контекстных положений. Следующие параметры поддерживаются для контекстного положения geo:

context

Объект географической точки или строка геохеша для фильтрации или усиления предложения. Это обязательно.

boost

Коэффициент, с которым должен усиливаться балл предложения; балл вычисляется путем умножения коэффициента усиления на вес предложения, по умолчанию 1

precision

Точность геохеша для кодирования географической точки запроса. Это можно указать как значение расстояния (5m, 10km и т. д.) или как исходную точность геохеша (1..12). По умолчанию используется точность на момент индексирования.

neighbours

Принимает массив значений точности, по которым должны учитываться соседние геохеши. Значение точности может быть значением расстояния (5m, 10km и т. д.) или исходной точностью геохеша (1..12). По умолчанию генерируются соседи для точности на момент индексирования.

Поле точности не приводит к совпадению по расстоянию. Указание значения расстояния, например, 10km, приводит только к значению точности геохеша, которое представляет собой плитки такого размера. Точность будет использоваться для кодирования географической точки поиска в плитку геохеша для соответствия завершению. Следствием этого является то, что точки за пределами этой плитки, даже если они очень близки к точке поиска, не будут сопоставлены. Уменьшение точности или увеличение расстояния может уменьшить риск этого, но не устранить его полностью.

Возвращение типа предсказателя

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

Рассмотрим следующий пример с двумя предсказателями term и phrase:

resp = client.search(
    typed_keys=True,
    suggest={
        "text": "some test mssage",
        "my-first-suggester": {
            "term": {
                "field": "message"
            }
        },
        "my-second-suggester": {
            "phrase": {
                "field": "message"
            }
        }
    },
)
print(resp)
response = client.search(
  typed_keys: true,
  body: {
    suggest: {
      text: 'some test mssage',
      "my-first-suggester": {
        term: {
          field: 'message'
        }
      },
      "my-second-suggester": {
        phrase: {
          field: 'message'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  typed_keys: "true",
  suggest: {
    text: "some test mssage",
    "my-first-suggester": {
      term: {
        field: "message",
      },
    },
    "my-second-suggester": {
      phrase: {
        field: "message",
      },
    },
  },
});
console.log(response);
POST _search?typed_keys
{
  "suggest": {
    "text" : "some test mssage",
    "my-first-suggester" : {
      "term" : {
        "field" : "message"
      }
    },
    "my-second-suggester" : {
      "phrase" : {
        "field" : "message"
      }
    }
  }
}

В ответе имена предсказателей будут изменены соответственно на term#my-first-suggester и phrase#my-second-suggester, отражая типы каждого предложения:

{
  "suggest": {
    "term#my-first-suggester": [ 
      {
        "text": "some",
        "offset": 0,
        "length": 4,
        "options": []
      },
      {
        "text": "test",
        "offset": 5,
        "length": 4,
        "options": []
      },
      {
        "text": "mssage",
        "offset": 10,
        "length": 6,
        "options": [
          {
            "text": "message",
            "score": 0.8333333,
            "freq": 4
          }
        ]
      }
    ],
    "phrase#my-second-suggester": [ 
      {
        "text": "some test mssage",
        "offset": 0,
        "length": 16,
        "options": [
          {
            "text": "some test message",
            "score": 0.030227963
          }
        ]
      }
    ]
  },
  ...
}

Имя my-first-suggester теперь содержит префикс term.

Имя my-second-suggester теперь содержит префикс phrase.

© 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/search-suggesters.html

Spec-Zone.ru

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