За чистый и ясный код!

Статьи на тему программирования под веб, используя PHP, MySQL, Jquery и многое другое

Как построить запрос типа WHERE MATCH AGAINST в Kohana3

Сентябрь2

Конструктор запросов

Нравиться мне Фреймворк Kohana, он легкий простой, пока дает все что мне нужно от моих задач.

И вот случилось у меня некая трудность, как я думал в начале, с написание запроса в условиях которого содержится конструкция MATCH(col1, col2,…) AGAINST(»text search»). На данный момент ORM я не юзаю, т.к. не представляю как можно там получить записи при объединении нескольких таблиц, ил запись с таблицы со сложным условием, но то ли еще будет…

Немного отступлю от проблемы, вкратце расскажу, для непосвященных, что это за конструкция. Это конструкция позволяет делать полнотекстовый поиск в наборе указанных полей. Имеет некие настройки для поиска, ищет в указанных полях. Для работы нужна таблица только! типа MyISAM, а также индекс FULLTEXT на искомые поля. Поля должны быть типа VARCHAR, CHAR, TEXT. Более детально на официальной документации.

И так, нужно составить запрос типа:

SELECT * FROM `table` WHERE MATCH(`col1`) AGAINST("search text");

Можно поступить двумя способами.
1 Просто написать такой запрос и запихнуть его в конструкцию:

$data = DB::query(Database::SELECT, 'SELECT * FROM `table`
WHERE MATCH(`col1`) AGAINST("search text")')->execute()->as_array();

В переменной $data у нас будет результат запроса.

Это самый простой способ получения запроса, но иногда такого мало. Например у меня есть запрос на поиск, который включает себя много полей, разные условия поиска и еще разные условия сортировки. В таком случае уж трудно будет изменять запрос… (У меня в модели несколько методов наразные части запроса — очень удобно управлять запросом).

2 Более сложным, но более эффективным путем при решении сложных запросов лучше пользоваться конструктором запросов. Данный пример вверху можно записать так (пока без части с уловием):

$data = DB::select()->from('table')->execute()->as_array();

Теперь как же быть с условием? Для условий where() существует целый класс Database_Query_Builder_Where в нем содержаться куча методов для построения запросов с логикой AND и OR.
Сам запрос сводиться к 3-м обязательным параметрам:

$db->where('column', 'operator', 'value');
например WHERE id=2 будет записано в виде:
$db->where('id', '=', 2);

Причем если значение это integer кавычек не будет, а если string система сама поставит кавычки.

Вернемся к нашему выражению.

SELECT * FROM `table` WHERE MATCH(`col1`) AGAINST("search text")

Что же здесь у нас столбец, что оператор и что значение??? Поставив такое выражение

$db->where('MATCH(col1)', '', 'AGAINST ("search text")');

я получи вид

WHERE `MATCH(col1)` 'AGAINST(\"search text\")'

естественно запрос не сработал… Немного поразмыслив я попытался обратиться к классу DB::expr(), который позволяет вставить в запрос выражение «как есть», т.е. не обрамляет его символами ` . И вот что получилось:

$query_m = DB::expr(' MATCH(`col1`) ');
$query_a = DB::expr(' AGAINST(addslashes("search text")) ');

$db->where($query_m, '', $query_a);

Естественно при использовании класса DB::expr() приходиться самому заботиться об SQL-инъекциях добавляя ф-цию addslashes, в итоге получилось выражение вида:

WHERE MATCH(`col1`) AGAINST("search text")

И так, подводим итог всей этой ночной писанины:

Для использования в условиях запроса сложных выражений при использовании конструктора запросов, необходимо прибегать к помощи класса DB::expr().
Вот полный пример:

$query_m = DB::expr(' MATCH(col1) ');
$query_a = DB::expr(' AGAINST(addslashes("search text")) ');

DB::select()->from('table')->where($query_m, '', $query_a);

получим запрос вида:

SELECT * FROM `table` WHERE MATCH(col1) AGAINST("search text")

Также можно построить такой запрос:

SELECT * FROM `table` WHERE FIELD_IN_SET('1,2,4,5', `column`);

пишем

$f = DB::expr(' FIND_IN_SET('1,2,4,5', ');
$c = DB::expr(' `column` ');

DB::select()->from('table')->where($f, '', $c);

В итоге

SELECT * FROM `table` WHERE FIELD_IN_SET('1,2,4,5', `column`)

Всем удачи в работе!

Статья просмотренна 85874 раз, зашло посетителей 22384

рубрика: Kohana

9 комментариев в “Как построить запрос типа WHERE MATCH AGAINST в Kohana3”

  1. Avatar
    biakaveron пишет:

    Почему не использовать Database::instance()->escape($var)?
    1. Данный метод удобно экранирует различные значения (числа, строки, массивы, объекты Database_Expression).
    2. Он не привязан к конкретной СУБД — все решает текущий драйвер.

    В целом, реализацию таких СУБД-зависимых конструкций желательно было бы прятать в реализацию драйвера. Но в принципе и так неплохо (если все это будет осуществляться в методах модели, а не контроллера).


  2. Avatar
    maxnag пишет:

    Эээ… ну честно как-то не вглядывался в дебри класса, спасибо большое за наводку, буду юзать его. Сейчас вот глянув в указанный тобой класс и увидел много плюшек. Спасибо.


  3. Avatar
    ags пишет:

    Почему бы не использовать бинд переменные? Это будет самое правильное решение…


  4. Avatar
    maxnag пишет:

    Покажи как можно ими пользоваться, какие + и -. Развей тему.


  5. Avatar
    загадки пишет:

    Чтож! Не плохой вариант для поиска. Конечно как и все варианты имеет свои особенности, но куда без них. Многопараметровый поиск заинтересовал.


  6. Avatar
    patap пишет:

    DB::select()->from('table')->where(DB::expr(' MATCH(col1) '), '', DB::expr(' AGAINST(:search) ', array(':search' => $search_text)));


  7. Avatar
    maxnag пишет:

    А чем Ваше выражение отличается от моего? Только тем что я вынес две составляющие в разные переменные?


  8. Avatar
    Павел пишет:

    Статья хорошая. Единственное можно добавить про AGAINST по больше и про релевантность выдачи.


  9. Avatar
    maxnag пишет:

    Павел, рассказ о работе данной конструкции выходит за рамки данной статьи, статья была о том, как именно делать такие запросы на данном фрейме.


не публикуется

пример

Оставить комментарий или два:

  

Облако тегов

cli csv dump events form Kohana locale models MySQL mysqldump orm PHP tools trigger validate газ газовый счетчик итоги кеширование переменные

Облако тегов плагина WP Cumulus для WordPress требует для просмотра Flash Player 9 или выше.

Я на твиттере!

  • у твиттера тоже бывают перерывы...

Календарь

Сентябрь 2010
Пн Вт Ср Чт Пт Сб Вс
« Июл   Окт »
 12345
6789101112
13141516171819
20212223242526
27282930  

Сейчас на сайте