Реализация EAV Laravel

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

Дано:

Структура SQL (тык по выполнить код)

const products = [{ id: 1, name: 'Product 1', price: 100 },{ id: 2, name: 'Product 2', price: 200 },];const properties = [{ id: 1, name: 'Color', slug: 'color', type: 'string' },{ id: 2, name: 'Size', slug: 'size', type: 'string' },];const propertiesList = [{ id: 1, property_id: 1, value: 'Red' },{ id: 2, property_id: 2, value: 'Large' },];const productProperties = [{ id: 1, product_id: 1, property_id: 1, value: 'Red' },{ id: 2, product_id: 1, property_id: 2, value: 'Large' },];function createTable(title, data, columns) {let table = `<p>${title}</p><table border="1"><tr>`;columns.forEach(col => {table += `<th>${col}</th>`;});table += '</tr>';data.forEach(row => {table += '<tr>';columns.forEach(col => {table += `<td>${row[col]}</td>`;});table += '</tr>';});table += '</table>';return table;}document.body.innerHTML += createTable('Products', products, ['id', 'name', 'price']);document.body.innerHTML += createTable('Properties', properties, ['id', 'name', 'slug', 'type']);document.body.innerHTML += createTable('Properties List', propertiesList, ['id', 'property_id', 'value']);document.body.innerHTML += createTable('Product Properties', productProperties, ['id', 'product_id', 'property_id', 'value']);
table {margin: 20px;} body {display:flex}

В чем суть:

Допустим, продуктами будут автомобили. На сайте будет вкладка с фильтрами, где можно в одном запросе фильтровать по: цене, марке, году выпуска, цвету, кузову, в будущем допустим добавить фильтр по наличию автодоводчиков. Напомню, любое количество фильтров (конечно, в пределах разумного), должно не превышать 500мс.

Пробовал средствами Eloquent с whereHas, с join'ами, и время запроса растет по экспоненте по отношению к количеству фильтров в обоих случаях (при 12-ти фильтрах запрос 30000мс).

SQL запросы, к примеру, удалось реализовать примерно такие:

SELECT `products`.*
FROM `products`
WHERE EXISTS (
    SELECT 1
    FROM `product_properties` AS `pp1`
    WHERE `products`.`id` = `pp1`.`product_id`
    AND `pp1`.`property_id` = 1
    AND `pp1`.`value` = 'Value1'
)
AND EXISTS (
    SELECT 1
    FROM `product_properties` AS `pp2`
    WHERE `products`.`id` = `pp2`.`product_id`
    AND `pp2`.`property_id` = 2
    AND `pp2`.`value` = 'Value2'
)
...
AND `products`.`price` BETWEEN 100 AND 500
AND `products`.`name` LIKE '%Product%'
ORDER BY `products`.`price` ASC;

или

SELECT p.id, p.name, p.price
FROM products p
JOIN product_properties pp1 ON p.id = pp1.product_id AND pp1.property_id = 1 AND pp1.value = 'Value1'
JOIN product_properties pp2 ON p.id = pp2.product_id AND pp2.property_id = 2 AND pp2.value = 'Value2'
JOIN product_properties pp3 ON p.id = pp3.product_id AND pp3.property_id = 3 AND pp3.value = 'Value3'
...
WHERE p.price BETWEEN 100 AND 500
AND p.name LIKE '%Product%'
ORDER BY p.price ASC;

Итог:

Нужна помощь в оптимизации запроса, некий совет, какими инструментами достичь желаемого, возможно ли это реализовать с помощью ёлки или же вкрапывать сырые sql запросы...


Ответы (0 шт):