Классификатор товаров Яндекс.Маркет - insbor.ru
insbor.ru

insbor.ru

Привет, это я

Читаю, пишу, перечитываю и исправляю.


Что здесь происходит


Предыдущие записи


Классификатор товаров Яндекс.Маркет

Опубликовано :   |  Кем :   |  Категория :  Классификаторы

Добрый день! В коллекцию к предыдущим записям шестилетней (кошмар!) давности добавлю классификатор (справочник) категорий товаров с Яндекс.Маркета. За актуальность не отвечаю, так что если нужна свежая копия, можно скачать с официального сайта: download.cdn.yandex.net.

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

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

Closure Table хороша для сложной, но не очень объёмной структуры, а у нас всего-навсего классическое дерево.

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

Авто > Аксессуары > Зеркала заднего вида

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

CREATE TABLE `product_categories` (
    `id` int(10) UNSIGNED NOT NULL,
    `name` varchar(255) NOT NULL,
    `path_name` varchar(255) NOT NULL,
    `path` varchar(255) DEFAULT NULL,
    `description` varchar(255) DEFAULT NULL,
    `parent_id` int(11) DEFAULT NULL,
    `ns_left` int(11) DEFAULT NULL,
    `ns_right` int(11) DEFAULT NULL,
    `ns_depth` int(11) NOT NULL DEFAULT '0',
    `order` int(11) DEFAULT '0',
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` timestamp NULL DEFAULT NULL,
    `deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `product_categories`
    ADD PRIMARY KEY (`id`),
    ADD UNIQUE KEY `parent_name_index` (`parent_id`,`name`),
    ADD KEY `name` (`name`),
    ADD KEY `path_name` (`path_name`),
    ADD KEY `path` (`path`),
    ADD KEY `parent_id` (`parent_id`),
    ADD KEY `ns_left` (`ns_left`),
    ADD KEY `ns_right` (`ns_right`),
    ADD KEY `order` (`order`);

Обратите внимание на поле deleted_at. Я использовал этот справочник в Laravel, так что с помощью Eloquent можно реализовать псевдо-удаление. Непосредственно для работы с логикой дерева использую Nested Sets, а поля от Materialized Path - только для хлебных крошек. Поскольку в справочниках структура меняется крайне редко, то пересчитывать при этом поля path и path_name не составит труда. Реализацию для ORM взял отсюда: github.com/etrepat/baum.

Скачать (.zip 111Кб) бэкап полученной таблицы, справочник категорий с Яндекса и сидер для Eloquent.