Использование полнотекстового индекса во views

Главные вкладки

Аватар пользователя edhel edhel 30 октября 2010 в 8:05

Во views есть возможность сделать полнотекстовый поиск по полю, но будет использоваться медленный оператор LIKE '%слово%' (на больших массивах данных). В MySQL есть полнотекстовый индексы (http://dev.mysql.com/doc/refman/5.0/en/create-index.html, http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html).

Вот как можно заставить views использовать полнотекстовый индекс с помощью оператора MATCH:

1. Ручками создаём полнотекстовый индекс, например, по полю node.title.
2. Добавляем во views фильтр по полю node.title на равенство с учётом регистра (можно сделать его "exposed").
3. Пишем модуль mymodule c хуком views_query_alter:

<?php
function mymodule_views_query_alter(&$view, &$query) {
if ($view->name == 'MYVIEW_NAME') {
$args_count = 0;
foreach ($query->where[0]['clauses'] as $key => $value) {
if (strstr($value, '%s')) $args_count++;
if ($value == "(node.title) = ('%s')") {
$query->where[0]['clauses'][$key] = "MATCH (node.title) AGAINST ('%s' IN BOOLEAN MODE)";
_mymodule_views_query_alter_hepler($query->where[0]['args'][$args_count - 1]);
}
}
}
}

function _mymodule_views_query_alter_hepler(&$s) {
$words = preg_split("/\s+/", trim($s));
$new_words = array();
foreach ($words as $word) {
$first = drupal_substr($word, 0, 1);
if ($first != '+' && $first != '-') {
$word = '+' . $word;
}
$new_words[] = $word;
}
$s = join(' ', $new_words);
}

?>

Вторая вспомогательная функция добавляет ко всем словам запроса "+", чтобы искались ноды в которых есть ВСЕ слова запроса, т.к. по умолчанию используется связка ИЛИ. Если это не нужно, то код можно упростить:

<?php
function mymodule_views_query_alter(&$view, &$query) {
if ($view->name == 'MYVIEW_NAME') {
foreach ($query->where[0]['clauses'] as $key => $value) {
if ($value == "(node.title) = ('%s')") {
$query->where[0]['clauses'][$key] = "MATCH (node.title) AGAINST ('%s' IN BOOLEAN MODE)";
}
}
}
}
?>

Кстати язык запросов поддерживает операторы +, -, "цитата" и *.