← назад к разделу

Официальный клиент @elastic/elasticsearch выполняет HTTP-запросы к кластеру и возвращает promises. Приложению остается выбрать модель документа, mapping и момент, когда новая запись должна стать видимой поиску.

Индекс и mapping

Mapping описывает поля и их типы. Текст для полнотекстового поиска - text, числовая цена - double, точное ключевое значение - keyword.

import { Client } from '@elastic/elasticsearch';

const client = new Client({ node: process.env.ELASTIC_URL });

await client.indices.create({
  index: 'products',
  mappings: {
    properties: {
      name: { type: 'text' },
      price: { type: 'double' },
      sellerId: { type: 'keyword' },
    },
  },
});

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

Запись и чтение

index создает или заменяет документ по ID, update меняет часть, delete удаляет. Для сценария «написали и сразу ищем» нужен явный refresh:

await client.index({
  index: 'products',
  id: '42',
  document: { name: 'Кофемолка', price: 4990, sellerId: '7' },
  refresh: 'wait_for',
});

Без refresh документ может быть доступен по ID, но еще не попасть в поисковый результат. wait_for ждет следующего refresh, а не делает любую запись мгновенно бесплатной.

Поиск

const result = await client.search({
  index: 'products',
  query: {
    multi_match: {
      query: 'кофемолка',
      fields: ['name^2', 'description'],
    },
  },
});

name^2 повышает вес названия относительно описания. Не складывайте в поиск фильтр по цене и права доступа постфактумом в JavaScript: фильтры исходной выборки принадлежат запросу, иначе пагинация и ранжирование будут неверными.

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

Коротко

  • Mapping и создание индекса - provisioning, не каждый запрос.
  • index, update, delete - разные операции.
  • refresh: 'wait_for' нужен для чтения сразу после записи.
  • Вес полей и фильтры задают в поисковом запросе.
  • Ошибки и отмена обрабатывают явно.

Что почитать дальше