Когда ресурс вырастает из объема одной страницы, уже целесообразно, для удобства использования, добавить на сайт поиск. Поисковые механизмы бывают разные. Для блога, типа этого, вам вполне хватит

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

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить