Symfony с Zend Lucene и родственными моделями (с внешними ключами)
Ну, я разрабатывал приложение для Symfony 1.4 и Doctrine, когда осознал серьезный недостаток моей реализации Zend Lucene.
У меня есть модель под названием "Публикация", которая связана (через отношения внешнего ключа) с несколькими другими моделями (предметами, жанрами, языками, авторами и т. Д.), И я получаю их имена при добавлении нового документа в индекс (используя методику Jobeet), чтобы я мог искать публикации с заданной темой, жанром, языком, автором и т. д.... Проблема в том, что если по какой-то причине я решу изменить имя одной из этих связанных моделей Zend Lucene Индекс не будет обновляться.
Единственные два решения, которые я мог придумать, были:
Регулярно переиндексируйте все публикации, чтобы гарантировать, что любые изменения, внесенные в соответствующие модели, будут обновлены в индексе (однако это решение не позволяет обновлять индекс в режиме реального времени).
Получите все публикации, связанные с данной моделью, и переиндексируйте их после обновления (используя save(), postSave(), postUpdate() или все, что вы можете придумать в Doctrine). -> Это решение выглядело великолепно... Оно будет перестраивать индекс только для публикаций, которые связаны с обновленной моделью, верно? Что ж, если у вас есть что-то вроде тысячи (1000) публикаций, связанных с ним, обновление займет несколько минут (да, я проверял это), а в пользовательской форме это произойдет, потому что это займет более 30 секунд (и даже если это не так). t было бы плохо, если бы пользователь несколько минут смотрел на экран в ожидании загрузки страницы).
Так что я хочу знать, есть ли другое решение? Есть ли способ обновить индекс на лету, основываясь на изменении связанной модели, не повесив весь пах? Может, поставить задачу на фон или что-то еще? Есть ли такой способ?
Если нет способа сделать это с Lucene, есть ли способ использовать полнотекстовый поиск с MySQL (с таблицами InnoDB) без использования Zend Lucene, у которого нет такого недостатка? Если есть такой инструмент, я бы с радостью реорганизовал мой код, чтобы приспособить его к другой библиотеке.
Не могли бы вы помочь мне с этим? Заранее спасибо!
2 ответа
Ну... я отвечаю сам. Подумав некоторое время, я пришел к компромиссному решению.
В моей модели у меня уже есть отношение "один к одному" с таблицей, которая используется только для хранения метаинформации о публикации, поэтому я в итоге вставил новый столбец с именем reindex (то есть "булево"). Таким образом, каждый раз, когда я обновляю сущность, связанную с публикацией (что-то, что в производстве случается очень редко, но я хочу быть готовым к ней), она будет помечать каждую связанную с ней публикацию как нужную для переиндексации. Тогда у меня есть задача, которую можно запустить на задании cron или планировщике задач, который будет только переиндексировать публикации, помеченные как нуждающиеся в этом. Таким образом, я могу настроить запуск этой задачи несколько раз в неделю в поздние часы, чтобы индекс был согласованным.
Это не идеальное решение, но лучшее, что я могу придумать, используя только PHP и Zend Lucene.
Документ Lucene не может быть обновлен. Вы можете только удалить попадания и повторно добавить их обратно. По этой причине мое первоначальное решение недействительно.
Я искал альтернативы для вас, и есть один, который попался на глаза: http://www.sphinxsearch.com/
Кажется, что Sphinx очень быстро индексирует, но выполняет поиск медленнее. Может быть стоит посмотреть.
Из того, что я читал, реализация Lucene на PHP не очень быстра, и это нормальное поведение. Существуют способы повысить скорость индексации больших объемов данных, которые в основном включают увеличение объема оперативной памяти, чтобы Lucene мог записывать в память документы большего размера, прежде чем выгружать файлы.