Масштабируемый полнотекстовый поиск с заказом результатов по каждому пользователю
Какие существуют варианты создания масштабируемого полнотекстового поиска с результатами, которые необходимо отсортировать для каждого пользователя? Это для PHP/MySQL (также Symfony/Doctrine, если применимо).
В нашем случае у нас есть база данных тренировок, которые были выполнены пользователями. Тренировки, которые пользователь выполнял ранее, должны отображаться в верхней части результатов. Чем чаще они выполняют тренировку, тем выше она должна появляться в результатах поиска. Если это поможет, вы можете предположить, что мы знаем, сколько раз пользователь выполнял тренировку заранее.
Возможные решения
Sphinx - используйте Sphinx для реализации полнотекстового поиска, выполняйте все запросы и сортировку в MySQL. Это кажется многообещающим (и есть плагин Symfony!), Но я не знаю много об этом.
Lucene - используйте Lucene для выполнения полнотекстового поиска и добавления пользовательских запросов в запрос. Как предлагается в этом потоке переполнения стека. Либо используйте Lucene для получения результатов, а затем измените их порядок в PHP. Однако оба решения кажутся неуклюжими и потенциально не масштабируемыми, поскольку пользователь, возможно, выполнил сотни тренировок.
Mysql - Нет встроенной полнотекстовой поддержки (InnoDB), поэтому нам пришлось бы использовать LIKE или REGEX, которые не масштабируются.
2 ответа
MySQL
есть родной FULLTEXT
поддержка, правда, только в MyISAM
столы.
Для большинства реальных задач, Sphinx
самый быстрый двигатель Однако это внешний индекс, поэтому его можно своевременно обновлять только с помощью скрипта cron.
Используя SphinxSE
(подключаемый MySQL
интерфейс к Sphinx
), ты можешь присоединиться MySQL
столы и Sphinx
индексы в одном запросе. Обновление, тем не менее, все еще потребует внешнего сценария.
Поскольку количество выполненных тренировок часто меняется, Sphinx
потребует слишком много усилий для перестройки индекса.
С SphinxSE
Вы можете написать запрос, подобный следующему:
SELECT *
FROM workouts w
JOIN user_workouts uw
ON uw.workout = w.id
WHERE w.query = 'query query query;filter=user_id,$user_id'
AND uw.user = $user_id
ORDER BY
uw.times_performed DESC
Я не уверен, почему вы предполагаете, что использование Lucene было бы невероятным. Сотни тренировок на одного пользователя - это не много данных, с которыми приходится иметь дело.
Попробуйте использовать Solr/Lucene для поиска. Он имеет интерфейс JSON/XML, который будет прекрасно сочетаться с вашим PHP-интерфейсом. Сохраните выполненную пользователем тренировку # в таблице базы данных. После выдачи запроса возьмите результаты из Solr, и вы сможете выбрать из таблицы базы данных и использовать PHP-код. Должно быть достаточно быстрым и масштабируемым. С Solr поддерживать ваш индекс очень просто; просто отправляйте запросы на добавление / обновление / удаление на ваш сервер Solr.