Поиск на сайте с помощью phpMorphy
Всем привет!
Заметка скорее всего больше для размышлений, но может кому пригодится.
Тут между делом за поиск зацепились и Василий сказал, что использует Sphinx. Я со сфинксом столкнулся еще году в 2009-ом и тогда его с наскоку не победил, но для себя уяснил четко: он весьма не прост. Но когда в свое время решил на своем сайте сделать поиск, нужно было что-то искать на замену, ведь важная часть поиска — это именно морфологический поиск.
В поисках решения я набрел на phpMorphy (конкретно этот пакет устаревший уже, но есть и более новые реализации). Суть его в том, чтобы делать разбор строки и определять леммы.
И вот в результате появился компонент modSearch. Исходники его я выложил: github.com/MODX-Club/modsearch
Возможно будет интересно покопать отдельный моменты по реализации. Часть из них опишу.
1. Плагин. Срабатывает на сохранение документа (событие OnDocFormSave).
К сожалению, в самом классе документа нет вызова ивента при сохранении, чтобы плагин срабатывал на любое изменение, пусть даже через API
Для сравнения в классе modUser прописаны вызовы при сохранении: github.com/modxcms/revolution/blob/2.x/core/model/modx/moduser.class.php#L92-L114
То есть на пользователя можно навесить плагин, который всегда сработает где и как бы не был сохранен пользователь (исключая случаи выполнения чистого SQL).
Не буду говорить, что это еще один недостаток MODX.
2. Создание поисковых индексов. github.com/MODX-Club/modsearch/blob/master/core/components/modsearch/model/modsearch/modsearch.class.php#L16
В системной настройке modsearch.index_fields можно перечислить поля, которые будут использоваться для создания поисковых индексов. При создании индексов скрипт берет эту системную настройку и из документа дергает эти поля. По-умолчанию это pagetitle, longtitle, content.
3. Переобход всех документов, чтобы создать для них индексы (выполняется в консоли).
github.com/MODX-Club/modsearch/blob/master/core/components/console/files/global/modxclub.ru/modsearch/resources/update_indexes.php
4. Скрипт для поиска документов через процессор компонента modxSite (так же выполняется в консоли).
github.com/MODX-Club/modsearch/blob/master/core/components/console/files/global/modxclub.ru/modsearch/resources/getdata.php
А вот здесь вот формируется итоговый запрос на выборку документов: github.com/MODX-Club/modxSite/blob/master/core/components/modxsite/processors/site/web/resources/getdata.class.php#L64
5. Установка «на лету» связи modResource->SearchIndexes.
github.com/MODX-Club/modsearch/blob/master/core/components/modsearch/model/modsearch/metadata.mysql.php
Могу точно сказать, что с небольшими модификациями это можно использовать и с минишопом (делал на паре сторонних сайтов) и на каталоге в несколько тысяч товаров вполне приемлемо ищет, в том числе и по скорости.
Заметка скорее всего больше для размышлений, но может кому пригодится.
Тут между делом за поиск зацепились и Василий сказал, что использует Sphinx. Я со сфинксом столкнулся еще году в 2009-ом и тогда его с наскоку не победил, но для себя уяснил четко: он весьма не прост. Но когда в свое время решил на своем сайте сделать поиск, нужно было что-то искать на замену, ведь важная часть поиска — это именно морфологический поиск.
В поисках решения я набрел на phpMorphy (конкретно этот пакет устаревший уже, но есть и более новые реализации). Суть его в том, чтобы делать разбор строки и определять леммы.
И вот в результате появился компонент modSearch. Исходники его я выложил: github.com/MODX-Club/modsearch
Возможно будет интересно покопать отдельный моменты по реализации. Часть из них опишу.
1. Плагин. Срабатывает на сохранение документа (событие OnDocFormSave).
К сожалению, в самом классе документа нет вызова ивента при сохранении, чтобы плагин срабатывал на любое изменение, пусть даже через API
$doc = $modx->getObject("modResource", $id);
$doc->set("content", $newContent);
$doc->save();То есть если обновить вот так, то плагин не сработает, он сработает только на сохранение документа через админку.Для сравнения в классе modUser прописаны вызовы при сохранении: github.com/modxcms/revolution/blob/2.x/core/model/modx/moduser.class.php#L92-L114
То есть на пользователя можно навесить плагин, который всегда сработает где и как бы не был сохранен пользователь (исключая случаи выполнения чистого SQL).
Не буду говорить, что это еще один недостаток MODX.
2. Создание поисковых индексов. github.com/MODX-Club/modsearch/blob/master/core/components/modsearch/model/modsearch/modsearch.class.php#L16
В системной настройке modsearch.index_fields можно перечислить поля, которые будут использоваться для создания поисковых индексов. При создании индексов скрипт берет эту системную настройку и из документа дергает эти поля. По-умолчанию это pagetitle, longtitle, content.
Здесь отдельно отмечу один из минусов моего решения: здесь нет никакого ранжирования. То есть не важно в заголовке слова были найдены или нет, вес их одинаковый. Или было найдено, или нет. С этой точки зрения у Василия конечно же лучше реализовано.
3. Переобход всех документов, чтобы создать для них индексы (выполняется в консоли).
github.com/MODX-Club/modsearch/blob/master/core/components/console/files/global/modxclub.ru/modsearch/resources/update_indexes.php
4. Скрипт для поиска документов через процессор компонента modxSite (так же выполняется в консоли).
github.com/MODX-Club/modsearch/blob/master/core/components/console/files/global/modxclub.ru/modsearch/resources/getdata.php
А вот здесь вот формируется итоговый запрос на выборку документов: github.com/MODX-Club/modxSite/blob/master/core/components/modxsite/processors/site/web/resources/getdata.class.php#L64
5. Установка «на лету» связи modResource->SearchIndexes.
github.com/MODX-Club/modsearch/blob/master/core/components/modsearch/model/modsearch/metadata.mysql.php
Могу точно сказать, что с небольшими модификациями это можно использовать и с минишопом (делал на паре сторонних сайтов) и на каталоге в несколько тысяч товаров вполне приемлемо ищет, в том числе и по скорости.
Комментарии: 16
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Только здесь, на modx.pro. Думал, что он получше mSearch2 работать будет, но пока что вышло, что это не так.
Fi1osofP.S. про здесь сфинкс — я так и думал. Но не знал, что phpMorphy у тебя в mSearch2 используется.
Sphinx — это отдельно крутящий демон, которому ты отдаёшь поисковый запрос и он делает всю работу. Включая, например, подсветку найденных слов.
Выглядит это примерно как SQL запрос, только не в БД, а в Sphinx
В mSearch2 же это всё делается вручную, используя формы слов от phpMorphy. Наверное можно просклонять слова в phpMorphy, потом поискать их в Sphinx, потом отдельно отранжировать и соединить ответы — но вряд ли это что-то улучшит, а вот усложнит — наверняка.
Я такого не нашёл. Есть только pymorphy2, но он на Python и его ни разу не использовал.
Его и имел в виду
Fi1osof1. innoDB не умеет в fulltext habr.com/ru/post/114572/ А я часто перевожу базу данных на innoDB, потому что MyIsam не умеет в foreign key, да еще и постоянно разваливается.
2. Если я расширяю таблицу и добавляю кастомные поля, то и индекс надо расширять.
3. Я могу хотеть не учитывать некоторые колонки.
4. Я могу хотеть добавить индексы сразу по нескольким таблица.
Вот и я приблизительно также аргументировал PR с выпиливанием этого монстра. Но Джейсон сказал, что чем больше индексов тем лучше. Хрен с ним, что некоторые не используются. Когда-нибудь кому-нибудь пригодится. Fuck the fuel economy and sql optimization!
Fi1osofНа тот момент я получал сообщение «Не могу создать такой индекс».
Я как раз хотел приступить к реализации морфологического поиска по своей кастомной таблице — тут много полезных моментов я нашел для себя!
Fi1osofFi1osofТак что если работает: то замечательно.
Но встречный вопрос: так работает из коробки или какая кастомизация выполнялась? Если кастомизация, то неплохо бы описать ее в отдельной статье. Но предполагаю, что кастомизации никакой особо не было (судя по объему потребляемой памяти). Значит просто сервер помощнее взят? Какие характеристики железа?
И если не сложно, кинь ссылку на свой магазин, чуть-чуть помучить его поисковыми запросами, чтобы посмотреть как быстро он работает.
Со своей стороны вот один из моих топиков про оптимизацию: modxclub.ru/blog/bolshoy-magazin-na-modx-revolution/172.html
Конкретно в этом топике ничего нет касаемого modSearch, но я когда тесты проводил, скорость при поиске не сильно отличалась.
Вариант для российской версии сайта сделал @Володя, так что это к нему.
6 x 2,4+ ГГц, 8192 МБ
Fi1osof3-4 секунды.
И да, сервер совсем не простой.
Что-то грустно, на самом деле.