Масштабируемый полнотекстовый поиск с заказом результатов по каждому пользователю

Какие существуют варианты создания масштабируемого полнотекстового поиска с результатами, которые необходимо отсортировать для каждого пользователя? Это для 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.

Другие вопросы по тегам