Когда ресурс вырастает из объема одной страницы, уже целесообразно, для удобства использования, добавить на сайт поиск. Поисковые механизмы бывают разные. Для блога, типа этого, вам вполне хватит
select * from material where innertext like '%xdan.ru%' or title like '%xdan.ru%' limit 10;
Она отлично работает, на сайтах с небольшой аудиторией и небольшим объемом информации. Но что если сделать то же самое для поиска из таблицы в несколько тысяч записей?
Если вы вспомнили про индексы, то они вам тут не помогут. Тот факт, что поиск ведется по всему полю %, а не с его начала, уже делает использование индексов невозможным. Т.е. запрос выше, тупо перебирает все строки и ищет соответствие. В больших таблицах это может занимать длительное время. Как же быть? Google нам сообщает, что есть такой зверь: полнотекстовый индекс и полнотекстовый поиск.
Но работают они только таблицах на движке MyISAM. В вышедшей ранее статье, мы конвертировали одну медленную таблицу в этот формат. Проделаем с таблице material тоже самое.
ALTER TABLE material ENGINE = MYISAM
А потом добавим пару полнотекстовых индексов
create FULLTEXT index full_index_title on `material`(`title`); create FULLTEXT index full_index_text on `material`(`innertext`);
Если вы делаете эти запросы в phpmyadmin, то не пугайтесь тому, что она показывает количество записей в индексе равное 1. Это глюк.
Сам запрос поиска тоже изменится
select * from material where MATCH (title) AGAINST ('*xdan.ru*' IN BOOLEAN MODE) or MATCH (innertext) AGAINST ('*xdan.ru*' IN BOOLEAN MODE) limit 10
Такой запрос отработает на ура. И в таблицах с более чем 100000 записей срабатывает за каких-нибудь 0.0062 сек..
Если в вашем запросе используется оператор and то имеет смысл объединить два индекса в один.
create FULLTEXT index full_index_title_text on `material`(`title`,'innertext');
А в выборке делаем
select * from material where MATCH (title,innertext) AGAINST ('*xdan.ru*' IN BOOLEAN MODE) limit 10
Такой запрос отработает быстрее.
Назначение звездочек аналогичны %xdan.ru%. Кроме них у полнотекстового поиска есть еще другие операторы (+,- и т.д.) По этому, и во избежание SQL инъекций, всегда делайте экранирование. SQL инъекции головная боль не только web программистов. У программистов мобильных приложений на такие платформы как Android или IOS, бывают схожие проблемы. Так как эти системы в своем нутре, имеют полноценную поддержку SQL запросов и для хранения данных использую некое подобие СУБД. И приложения соответственно тоже бывают разные. Если вы решили скачать карточные игры на андроид, то лучше сделать это из известных источников.
Полнотекстовый поиск, в отличии от LIKE ищет по своему алгоритму и не всегда это простое совпадение. Кроме того, в большинстве случаев на запрос улицы
ленин
Нужно вывести сперва Ленина, а уже потом Проспект Петленина. Как это сделать? Нужно после оператора select добавить сравнение строк и если строки совпадают то возвращать 1 иначе 0. А в запросе сделать order by эту величину desc
select *,IF(LEFT(LOWER(TRIM(addr)),7)="xdan.ru",1, 0) as srt from material where MATCH (title,innertext) AGAINST ('*xdan.ru*' IN BOOLEAN MODE) ORDER BY srt desc limit 10
Цифра 7 это длина фразы, которую мы ищем
"xdan.ru"
В реальных запросах ее нужно будет динамически вычислять при помощи mb_strlen