Сентябрь 4, 2018
Теги: Хайлоадблоки, ORM, Как это сделать?
Обычно полнотекстовый поиск становится необходим, когда количество элементов в таблице базы данных переваливает за сотни тысяч. Тогда использование обычных фильтров может стать невозможным ввиду длительности исполнения запроса.
Чтобы воспользоваться возможностями полнотекстового поиска mysql, не используя прямые запросы, в ORM и хайлоадблоках, которые являются его наследниками, можно использовать поле runtime:
$filter = array();
$runtime = array();
$q = "323418217"; // строка для поиска
$runtime[] = new \Bitrix\Main\Entity\ExpressionField('MYSEARCH', '1');
$filter['=MYSEARCH'] = new \Bitrix\Main\DB\SqlExpression('1 AND MATCH(UF_NAME,UF_PREVIEW_TEXT,UF_INN) AGAINST (?s)', "323418217");
/*
MATCH (field1,field2) AGAINST ('word') - поиск отдельных слов
MATCH (field1,field2) AGAINST ('word*' IN BOOLEAN MODE) - поиск с начала слова
Внимание: '*' в начале не сработает, возможны операторы '+', '-', '~', '<', '>'
https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html
По умолчанию, при использовании нескольких слов в запросе, они объединяются по условию ИЛИ
Системные переменные mysql:
ft_min_word_len (по умолч. 4) - минимальная длина слова для индексации
ft_max_word_len - максимальная длина слова для индексации
*/
$result = CompanyTable::getList(array(
'runtime' => $runtime,
'filter' => $filter,
'limit' => 10,
));
while ($arRow = $result->fetch())
{
print_r($arRow);
}
Чтобы данный код заработал, необходимо сначала создать полнотекстовый индекс для нужного поля (или нескольких полей одновременно):
В противном случае, при выполнении запроса будет выдаваться ошибка:
Пересоздать индексы для таблицы можно командой (в некоторых случаях, удаление и создание индекса заново может быть быстрее):