Pull to refresh

Comments 36

Круто. Но как подсказывает мне опыт Sphinx — идеальное решение, его использование существенно упрощает жизнь и серверу, и разработчику.
Смотря для каких целей, если там тысяча или десять тысяч небольших текстов, то сфинкс — это стреляние баллистическими ракетами по мухам, ибо fulltext проще построить, не требует отдельного демона и он realtime (сфинкс же реалтайм только имитироват может и то это не одной командой делается).

А вот если текста (или вообще записей-атрибутов) дофига — то да, сфинкс — король.
ладно вам. как вы решите вопросы релевантности и морфологии????
Не претендую на истину, но вопросы морфологии можно решить несложной регуляркой, отсекая окончания слов (эвристически, по количеству букв в 2-3 штуки). На моём проекте 6-летней давности для поиска по названиям такое очень неплохо работало для нечёткого поиска без учёта склонений и родов.
статья хорошая, спасибо, а вот с данным комментарием я ни разу не согласен.
Сфинкс — простой и быстрый способ. И легковесный. Поэтому пожалуйста, не «надо ля-ля» про баллистические ракеты разводить :)

ваш совет с яндекс сервером уж всяко ничуть не лучше, чем сфинкс, если в задачи входит создание поиска с русской морфологией (… а вот если помимо русского нужны ещё немецкая и английская морфология? куда у нас отправится яндекс.сервер? правильно — в /dev/null)

:)
не одной командой делается).

indexer --all --rotate --config /my/config/file.conf

какая вторая команда? :)
Я вообще-то не столько про поиск, сколько про полнотекстовый индекс и его возможости писал.
Если уж на то пошло, тогда уж и mnogosearch можно вспомнить, хоть он и морально устарел, и вообще дословно алгоримы расказать… Но статья все же несколько не об этом.
UFO just landed and posted this here
Ага, на виртуальных серверах и небольших проектах, ага) А искать то и в небольших проектах приходится :)
enartemy, вы как минимум опаздали на пару лет со статьёй…
Знаете, а лучше поздно, чем никогда. :-)
Только вчера начал пробовать Sphinx, но статью почитал, спасибо =)
— Кстати, на эту схему очень хорошо ложится тегирование информации, но там не все так просто и это опять же отдельная тема.

почитал-бы с удовольствием — автор пиши еще!
пожалуйста, добавьте в таги русские слова: «полнотекстовый поиск» «поиск»
Респект автору! Давно искал статьи на эту тему и вот те на… Спасибо огромное!
Ошибочку в начале исправьте:
Главная особенность – быстрый поиск слов в очень больших объемах тестовой информации.
UFO just landed and posted this here
позволю себе немного оффтопа:
есть несколько миллионов файлов (в пределах 1-10). приходится искать файлы по их метаданным (имя и мозможно диапазон fileSize). в сущности обычный поисковик файлов. таких велосипедов много в локальных сетях.

идеальным вариантом для такой системы будет СУБД (пусть будет mysql) с очень быстрым LIKE '%%'. к сожалению приходится иметь дело с реальными системами с постоянными апдейтами таблиц (удаление старых ссылок на файлы, добавление новых ссылок на файлы) и LIKE '%%' жутко тормозит.

писать собственную СУБД накладно. LIKE неэффетиивен. скорее всего прийдется реализовать движок в котором реляционная СУБД будет использоваться как support tool. сейчас остановился на варианте с токенизацией — индексом с токенами из имен файлов. пытаюсь придумать наименее дешевую реализацию.
возможно среди заинтересовавшихся этой статьей есть опытные архитекторы и просто жертвы высоких нагрузок :)
Sphinx посмотрите.
В базе будете первичные данные хранить без каких либо накладных индексов, а искать сфинксом — сказка.
Поиск по двум индексам и мердж этих индексов по ночам даст возможность риал-тайм индексации.
UFO just landed and posted this here
с токенами еще интереснее: можно отказаться от LIKE '%%' и отправлять запросы к маленькой табличке с |tokenId|fileId|. хорошая избирательность достигается при ширине токена в 3 символа. токены строятся только по полюfileName (путь к файлу в отдельном столбце и не токенизируется) выборка WHERE tokenName IN( 'tokenId' ) будет очень шустрой

при всей своей простоте это довольно дорогая схема. прийдется реализовывать только если не найду более простое, дешевое и элегантное решение.
ошибся :(
WHERE tokenId IN( 'tokenId', ..., 'tokenId' )
UFO just landed and posted this here
UFO just landed and posted this here
Раньше я считал вот эту статью лучшей по fulltext поиску в mysql на русском
valera.ws/2007.08.29~fulltext_search_in_mysql/#more-8
а теперь даже не знаю :)
Статья однобокая, речь идёт только о MySQL. Почему бы не указать сразу об этом в названии статьи?
Следовало внимательнее читать:

В статье рассказывается как работать с полнотекстовым поиском на примере БД MySQL, а так же приведу примеры «нестандартного» использования данного механизма.

Примеры — да, mysql. Но привденные алгоритмы относятся не только к mysql, а вообще полнотествому поиску.
кстати, Николай.
к сожалению, не удалось посетить во вторник мероприятие. вы не выложите где-нибудь матерьялец?
Кстати, несмотря на возможности алиасов, при запросах конструкцию приходится повторять в разных местах, что усложняет запросы. Вот например нельзя написать так:

SELECT *, MATCH (title, body) AGAINST ('database') as REL
FROM `articles`
WHERE REL > 0;

Если заменить WHERE на HAVING то можно и не повторять конструкцию. Надо только посмотреть, что будет быстрее HAVING или еще раз посчитать?
Я конечно могу ошибаться, но при HAVING необходимо GROUP BY, т.к. HAVING — это условие групповой операции. А с группировкой запрос палюбому будет работать медленее.
В стандарте необходимо, но на mysql можно без GROUP BY.
Испытано на mysql 5.0.24
Цитата из документации:
A HAVING clause can refer to any column or alias named in a select_expr in the SELECT list or in outer subqueries, and to aggregate functions. However, the SQL standard requires that HAVING must reference only columns in the GROUP BY clause or columns used in aggregate functions.
Специально проверил. Вот выводы:

Да, действительно, с HAVING делать можно. Но!

EXPLAIN SELECT *, MATCH (title, body) AGAINST ('database') as REL FROM `articles` HAVING REL > 0;

Даёт:
possible_keys: NULL
keys: NULL
rows: 6
extra: NULL

EXPLAIN SELECT *, MATCH (title, body) AGAINST ('database') as REL FROM `articles` WHERE MATCH (title, body) AGAINST ('database') ;

Даёт:
possible_keys: ft1
keys: ft1
rows: 1
extra: Using where

— то есть, это работает, но лучше этого не делать. Ключи таблицы аналогичны примеру в статье.
Тест на MySQL 4.1.16
Все правильно, имменно поэтому в мане по mysql написано что лучше использовать where.
Поэтому же в начальном комментарии я и написал что нужно сначала проверить скорость выполнения запроса в одном и втором случае. Для данного случая можем получить выигрыш в скорости, а может и нет.

У вас ошибки в падежных окончаниях числительных:

  • из не менее третьих не пробельных символов

  • поиск по вторым полям

  • индекс вторых полей

  • таблица с вторымя полнотекстовыми индексами

  • длинной менее третьих символов

  • с третьеей таблицей

Sign up to leave a comment.

Articles

Change theme settings