1. Обзор
Описание
Сервис Search DSL предоставляет высокоуровневый, удобный язык запросов (DSL) для фронтенд-разработчиков. Он абстрагирует сложность работы с исходными запросами Elasticsearch, обеспечивая единообразную, безопасную и поддерживаемую функциональность поиска на нескольких e-commerce сайтах.
Скоуп
- Фронтенд: Используют DSL для поисковых запросов с помощью компактного REST/JSON API.
- Бэкенд: Сервис преобразует кастомные DSL-запросы в запросы Elasticsearch и возвращает нормализованные результаты поиска.
Цели
- Единообразие: Обеспечить одно решение для поиска на нескольких платформах e-commerce.
- Поддерживаемость: Централизовать логику поиска для упрощения обновлений, расширений и исправлений ошибок.
- Удобство использования: Предоставить простую JSON-схему, чтобы разработчики не нуждались в знаниях Elasticsearch DSL или GraphQL.
- Мультисайтовость: Один сервис DSL для всех сайтов, идентифицируемый уникальным
site_id
.
2. Основные функции
-
Высокоуровневые запросы DSL
-
Пользователи отправляют запросы поиска в JSON, с
text
(основной текстовый запрос), набором типизированныхfilters
, а такжеlimit/offset
и сортировкой. -
Пример:
{ "request": { "text": "Водонагреватель", "filters": [ { "key": "category", "filter_type": "multi", "value": { "reference": [ "9f61a853-20d0-433a-9525-b2fe50fcfeb7" ] } }, { "key": "price", "filter_type": "range", "value": { "range": { "from": { "value": 100.0 }, "to": { "value": 300.0 } } } }, { "key": "is_available", "filter_type": "bool", "value": { "bool": true } } ] }, "limit": 10, "offset": 0, "sort": "relevance" }
-
Эта структура позволяет гибко расширять типы фильтров (мульти-выбор, диапазон, булевы значения и т. д.).
-
-
Фильтрация
- Каждый объект фильтра имеет:
- ключ, например,
"category"
,"price"
,"is_available"
- индикатор типа фильтра (например,
multi
,range
,bool
) - значения (например, массив ссылок, числовой диапазон, булевы значения).
- ключ, например,
- Сервис сопоставляет эти фильтры с соответствующими полями Elasticsearch. Например:
key: "category"
может соответствовать полюcategory_id
.key: "price"
может соответствовать числовому полюprice
.key: "is_available"
может быть булевым полем.
- Каждый объект фильтра имеет:
-
Пагинация
- Используйте
limit
(количество товаров на запрос) иoffset
(начальный индекс) для управления пагинацией. - Внутренне это переводится в
from = offset
иsize = limit
. - Пример:
limit = 10
,offset = 0
→ первые 10 товаров.
- Используйте
-
Сортировка
- По релевантности (по умолчанию): Сортировка по тому, как хорошо результаты соответствуют запросу.
- По цене (по возрастанию/убыванию):
price_asc
илиprice_desc
- По имени (по возрастанию/убыванию):
name_asc
илиname_desc
- По рейтингу/популярности:
rating_desc
,popularity_desc
(когда будут существовать рейтинги товаров или показатели популярности) - По дате (по новизне):
date_desc
,date_asc
(когда будут доступны даты создания или выпуска товаров) - По пользовательским полям: например,
sales_count_asc
,sales_count_desc
(в зависимости от доступных полей) - Фронтенд может передавать параметр
sort
, чтобы указать желаемый порядок. - Поле
"sort"
может быть чем-то вроде"relevance"
,"price_asc"
и т. д. - Сервис сопоставляет их с сортировками ES. Например,
"relevance"
→_score desc
,"price_asc"
→price ascending
.
-
Фасетная навигация
- Сервис может возвращать агрегированные данные (бренды, категории, ценовые диапазоны и т. д.) для панелей фильтров.
- См. эндпоинт
GET /facets
.
-
Автодополнение / предложения (опционально)
- Предоставляет частичные совпадения/предложения по мере ввода пользователем.
-
Безопасность / Ролевой доступ (опционально)
- Некоторые сложные запросы или функции индексации могут быть ограничены для авторизованных ролей.
-
Аналитика / Логирование (опционально)
- Сбор данных о использовании запросов, популярных запросах или кликах по результатам для оптимизации.
3. API Эндпоинты
Примечание: Поскольку поддерживаются несколько сайтов электронной коммерции, каждый запрос должен указывать, на какой сайт нужно выполнить запрос, обычно через параметр
site_id
. Это можно указать как параметр запроса (/search?site_id=...
) или внутри тела запроса.
3.1 POST /search
- Описание: Основной эндпоинт для поиска товаров с использованием DSL.
- Поддержка нескольких сайтов: Укажите
site_id
, чтобы запросить правильный индекс
Пример запроса
{
"site_id": "1ab2c3d4-5678-90ef-1234-567890abcdef",
"request": {
"text": "Водонагреватель",
"filters": [
{
"key": "category",
"type": "filter_type_multi",
"value": {
"reference": [
"9f61a853-20d0-433a-9525-b2fe50fcfeb7"
]
}
},
{
"key": "price",
"type": "filter_type_range",
"value": {
"range": {
"from": { "value": 100.0 },
"to": { "value": 300.0 }
}
}
},
{
"key": "is_available",
"type": "filter_type_bool",
"value": {
"bool": true
}
}
]
},
"limit": 10,
"offset": 0,
"sort": "relevance"
}
Пример ответа
{
"total": 42,
"limit": 10,
"offset": 0,
"hits": [
{
"id": "abc123",
"name": "Heater X",
"price": 1999,
"...": "другие поля..."
},
{
"id": "def456",
"name": "Heater Y",
"price": 2999,
"...": "другие поля..."
}
// ...другие товары...
]
}
Как получить все товары в категории
Для получения всех товаров в категории можно оставить пустое "text"
и указать только фильтр по категории:
{
"site_id": "1ab2c3d4-5678-90ef-1234-567890abcdef",
"request": {
"text": "",
"filters": [
{
"key": "category",
"type": "filter_type_multi",
"value": {
"reference": [
"91d26ba4-ea09-4547-9e63-c4022a65d287"
]
}
}
]
},
"limit": 20,
"offset": 0,
"sort": "relevance"
}
Пример ответа
{
"total": 42,
"limit": 10,
"offset": 0,
"hits": [
{
"id": "abc123",
"name": "Heater X",
"price": 1999
// ...другие поля...
}
// ...
]
}
3.2 GET /facets
- Описание: Возвращает агрегированные данные для фасетного поиска (например, количество брендов, категорий, ценовых диапазонов и т. д.).
- Поддержка нескольких сайтов: Укажите
site_id
как параметр запроса или заголовок. - Возможные параметры запроса:
site_id
для указания, с данными какого сайта работать.text
(поисковый запрос, необязательно).- Можно передавать контекст фильтров, чтобы фасеты отражали текущие фильтры пользователя.
Пример: Получение фасетов для конкретного сайта с некоторыми фильтрами
GET /facets?site_id=1ab2c3d4-5678-90ef-1234-567890abcdef&text=Heater&category=91d26ba4-ea09-4547-9e63-c4022a65d287&price_from=100&price_to=500
-
Сервис будет учитывать эти параметры для формирования запросов и вернет фасеты, соответствующих поиску по “Обогреватель” в категории
91d26ba4-ea09-4547-9e63-c4022a65d287
и ценовом диапазоне100-500
. -
Ответ (пример):
{ "brand": [ { "key": "Electrolux", "count": 42 }, { "key": "Philips", "count": 30 } ], "category": [ { "key": "Heaters", "count": 50 }, { "key": "Air Conditioners", "count": 10 } ], "price": [ { "key": 0, "count": 5 }, { "key": 500, "count": 8 } // ... ] }
Интеграция: вы получите фасеты, а затем сможете использовать их в массиве filters -> value -> reference
в ваших запросах POST /search
.
3.3 POST /autocomplete
(Опционально)
-
Описание: Предоставляет
suggestions
(частичные совпадения) по мере ввода текста пользователем. -
Поддержка нескольких сайтов: Укажите
site_id
в теле запроса или как параметр. -
Тело запроса:
{ "site_id": "1ab2c3d4-5678-90ef-1234-567890abcdef", "partial": "электр" }
-
Ответ:
{ "suggestions": ["электролюкс", "электрообогреватель"] }
3.4 GET /health
- Описание: Проверка состояния, чтобы подтвердить, что сервис работает.
3.5 POST /index
(Только для администраторов)
- Описание: индексация данных в Elasticsearch (ограничено для авторизованных пользователей или ролей).
- Поддержка нескольких сайтов: Укажите
site_id
4. Схема базы данных
В основном используется индекс Elasticsearch и возможно минимальные реляционные данные для аналитики или логов.
В этом разделе необходимо будет разместить ссылки на схемы индексов ES
- Маппинги Elasticsearch
- Пример полей:
id
,name
,full_name
(текст + подполе keyword)brand.name
(текст + keyword)price
(число)categories
(вложенные или массив строк)
- Пример полей:
- Опциональная реляционная база данных
- Может хранить логи, аналитику поиска или бизнес-данные, не подходящие для Elasticsearch.
5. Пожелания по Дизайну
- Масштабируемость
- Сервис должен масштабироваться горизонтально, возможно, с балансировщиком нагрузки.
- Безопасность
- только сервис DSL, а не сам Elasticsearch, выставляется наружу.
- Использование API ключей или токенов для публичного доступа.
- Производительность и кэширование
- Кэширование часто запрашиваемых фасетов или запросов.
- Использование doc-value полей для числовой сортировки или агрегаций.
- Поддержка синонимов и нечетких совпадений
- Реализация анализаторов или логики нечеткого совпадения для удобного поиска.
- Ролевой доступ
- Возможность ограничить индексацию или сложные запросы для некоторых ролей.
6. Будущие улучшения
- Продвинутая сортировка
- Взвешенная или на основе машинного обучения сортировка для улучшения релевантности.
- Рекомендательная система
- “Другие товары, которые могут вас заинтересовать” или персонализированные предложения.
- Аналитика и отчеты
- Отслеживание запросов, которые не дали результат, популярных запросов или поведения пользователей.
- Правила мерчандайзинга
- Ручная настройка приоритетов, специальные акции, приоритет по наличию.