Разбор строки поискового запроса — задача, которая быстро превращается в головную боль, как только захочется ввести синтаксис запросов. Если фразы типа +театр -большой разобрать еще просто, то при обработке запроса театр & ((малый & москва) | (большой & урюпинск)) без грамматики не обойтись.
В январе 2010 на спане появился модуль Search::Query, который на первый взгляд поможет разрулить некоторые проблемы разбора поисковых запросов и даже подготовить подзапросы для последующих обращений к собственно поиску и склеиванию методами MapReduce.
Модуль заменяет простую грамматику поискового запроса, предоствляя в замен несколько методов, которые позволяют быстро представить запрос в виде древовидной структуры.
Разбор строки выполняет инстанс $parser типа Search::Query::Parser. (Сам класс Search::Query не содержит рабочую логику.)
use Search::Query;
my $parser = Search::Query->parser();
Затем вызывают метод parse, передав ему поисковый запрос.
my $query = $parser->parse('большой театр');
Возвращаемое значение — значение типа Search::Query::Dialect::Native. Оно может быть преобразовано в строку (это поможет, например, визуально проконтролировать правильность разбора), хотя в простейшем случае она не сильно отличается от запроса:
+:большой +:театр
Кроме того, возможно пройтись по построенному дереву запроса, вызвав метод walk():
say $query->walk(\&my_walk);
Функция, ссылку на которую получает метод walk(), получает четыре параметра, содержащие объяснение частей запроса.
sub my_walk{
my ($clause, $dialect, $code, $prefix) = @_;
. . .
}
Модуль Search::Query позволяет создавать и собственные диалекты поисковых языков, наследуя их от Search::Query::Dialect, либо определяя типовые конструкции при создании парсера:
my $parser = Search::Query->parser({
and_regex => 'И',
or_regex => 'ИЛИ',
not_regex => 'НЕ',
});
Разумеется, ключевые слова возможно описывать и регулярными выражениями. Дополнительные параметры конструктора парсеров задают правила для слов пользовательского запроса, разделителей и т. д.
Комментировать