Как осуществить поиск Django моделей по наибольшему количеству совпадений свойств?
Всем привет, возник такой вопрос. Есть задача - реализовать нечто вроде фильтра товаров как на Яндекс.Маркете на Django.
Конкретизирую:
Есть класс модели, и соответственно, куча записей в БД, соответствующих это модели. На странице интерфейса будет форма с редактированием параметров этой модели, на выходе должен быть список из N инстансов этой модели, в которых наибольшее количество совпадений с введенными на странице значениями. Упорядочить, соответственно, по количеству совпавших свойств.
Почему спрашиваю:
В голову приходила следующая идея: брать из БД те строки, в которых есть хотя бы одно совпадение с введенными параметрами, и уже программно генерировать тот список. Но есть одно но, по такому запросу может получиться огромный массив объектов, а так как ожидается, что на странице этот список будет обновляться асинхронно, аяксом, по любому изменению одного из параметров пользователем, получится очень частый запрос очень большого объема данных, как бы это не сказалось на скорости, да и звучит крайне не оптимально.
Кто-нибудь сталкивался с реализацией подобного функционала? Какие алгоритмы и приемы для этого используются. или может в Django есть уже готовые инструменты (пусть даже от сторонних разработчиков) для решения таких задач?
Я не собираюсь отображать все объекты, и мне не нужен постраничный вывод. Мне нужно вывести N наиболее подходящих запросам пользователя объектов. N, допустим, равен 10. Пользователь выбрал параметры, если работать по моему алгоритму, выберется из БД, например, 100000 записей, из них мне нужно отдать браузеру лишь 10 с наибольшим количеством совпадений. Пользователь поменял один из параметров на единичку - новый запрос - снова выбирается 100500 записей, из них выбирается 10 наиболее подходящих и отдается клиенту. Вопрос в том, как минимизировать количество выбираемых объектов. Если делать как я сказал выше, по наличию хотя бы одного совпадения значения параметра - будет запрашиваться много объектов, которые в итоге отсеются.
потому что если выбирать тупо хотя бы с одним совпадением и LIMIT делать 10, то не факт что в выборку попадут строки с наибольшим количеством совпадающих параметров
въехал в проблему, тут бы я использовал elasticsearch там можно настроить такой способ получения данных, а релевантность он сам посчитает как раз на основе большего количества совпадения по параметрам ну и лимит можно указать, и выберет тольк оте что наиболее релевантные
Занимаюсь сейчас аналогичным вопросом.
У меня реализовано три модели
1. Товар
2. Название характеристики
3. Значение характеристики
3.1. Связь с товаром
3.2. Связь с названием характеристики
3.3. Значение характеристики
Поиск идёт по третей модели. Записей, по числу строк, много. Но данных в них хранится мало.
Первый запрос - достаём 3.3, получаем выбранное количество товаров. Второй запрос по ИД товаров из этого списка, вытаскивает уже сами товары.
Ещё есть вариант использовать поисковые движки, а не насиловать БД на поиск.
Подумал как можно минимизировать количество запросов к БД. Думаю делать через raw sql запрос следующим образом. Структура примерно как у Вашей БД.
Objects:
1) o_id PK
2) .... всякие параметры объектов по которым НЕ будет осуществляться поиск
Properties:
1) id PK
2) o_id FK Objects.o_id
3) value
Синтаксически правильный запрос сейчас написать не могу, проверить его работу негде, боюсь ошибиться, напишу лишь суть:
1) Делаем SELECT по полям Properties.o_id, COUNT(Properties.id) as cnt, Objects.(... нужные поля с информацией об объекте)
В качестве входных параметров от формы будет приходить JSON следующего вида:
[
{ property_id: x, value: y },
{ property_id: x, value: y },
{ property_id: x, value: y }
...
]
соответственно к запросу генерируем условия WHERE (Properties.id=property_id AND Properties.value=value) or ((Properties.id=property_id AND Properties.value=value)) OR ...
для каждого объекта из JSON'а
2) INNER JOIN соответственно Properties.o_id и Objects.o_id
3) GROUP BY Properties.o_id
4) ORDER BY cnt
5) LIMIT N - ограничиваем выборку нужным нам количеством
Надеюсь такой алгоритм сделает то, что мне нужно. Это лишь мысли вслух, возможно есть некоторые ошибки