Интернет-магазин продаёт авто-товары. Нужно искать пары рекомендуемых товаров в тех же категориях с учётом дополнительных статистических ограничений. Сейчас в голове крутятся варианты на MySQL и Neo4J. Судя по графикам производительности, мне нужен будет именно Neo4J, но я не понимаю, как реализовать поиск с учётом агрегатных функций.
Модель данных
У каждой покупки есть дата
В одной покупке не менее одного товара.
У каждого товара в покупке есть стоимость.
Стоимость на один товар может меняться, потому что есть инфляция, курс доллара, рекламные акции.
У каждого товара есть не менее одной категории.
С точки SQL была бы такая модель
CREATE TABLE `product` (
`productId` INT(11) NOT NULL,
PRIMARY KEY (`productId`),
);
CREATE TABLE `product_category` (
`productId` INT(11) NOT NULL,
`categoryId` INT(11) NOT NULL,
PRIMARY KEY (`productId`,`categoryId`)
);
-- purchasePair - это денормализованная пара из покупки
-- Означает, что товар productId с ценой price был в одном заказе с товаром
-- productPairId и таких пар будет несколько на одну покупку
CREATE TABLE `purchasePair` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`productId` INT(11) NOT NULL,
`purchasedAt` datetime NOT NULL,
`productPairId` INT(11) NOT NULL,
`price` decimal(13,2) NOT NULL,
PRIMARY KEY (`id`)
);
В частности, мне нужно выполнить поиск по такому запросу:
Для заданного товара найти 5 товаров в тех же категориях, но чтобы цена была не меньше чем у этого товара и первыми были те, которые покупают чаще за последние 30 дней.
Пример:
Были покупки:
1. "Фара модель 1" (категория "электрооборудование") за 1000р была куплена вместе с "Сигнал" (электрооборудование) за 500р
2. "Фара модель 2" (категория "электрооборудование") за 500р была куплена вместе с "Охлаждающая жидкость" (Технические жидкости) за 800р
3. "Фара модель 2" (категория "электрооборудование") за 500р была куплена вместе с "Набор ковриков" (Салон) за 1500р
Теперь если я сделаю запрос "пара для товара "Сигнал за 500 рублей", мне должен вернуть "Фара модель 1", потому что это тоже "электрооборудование", но цена выше чем у "Сигнал" и покупка была в последние 30 дней.
На SQL запрос был бы такой (приблизительно):
SELECT pc2.productId, -- найти парный товар
(SELECT COUNT(id) -- определить количество продаж
FROM purchasePair pr
WHERE ((pr.productId = pc.productId AND pr.productPairId = pc2.productId)
OR -- чтобы продажи были в паре
(pr.productId = pc2.productId AND pr.productId = pc.productId)
)
AND pr.price > '500 рублей' -- и цена больше чем у товара
AND purchasedAt > '30 дней назад' -- и не очень давно
) as cnt
FROM productCategory pc
JOIN productCategory pc2 ON pc2.categoryId = pc.categoryId -- и чтобы товары были в одной категории
WHERE pc.productId = 'Сигнал'
ORDER BY cnt DESC -- по убыванию количества продаж
LIMIT 5 -- только 5 результатов из найденных
Как такое же сделать на Neo4J?