В этой статье мы расскажем о регулярных выражениях и о том, как их использовать в Manticore Search
Если говорить о поиске текста, самым простым является сравнение строк. И поисковая строка, и документ или поле должны быть полностью одинаковыми. Следующий метод поиска текста — выполнение простого сопоставления шаблона, которое позволяет находить поисковую строку как часть поля. Такое простое сопоставление шаблона может использовать базовые операторы, такие как подстановочные знаки, где метасимволы * или % означают «соответствует любым символам». В базах данных это обычно реализуется оператором LIKE, например:
SELECT * FROM mytable WHERE title LIKE '%and%'
будет находить строки с заголовками, содержащими буквальный подстроку 'and'.
Регулярные выражения работают с обычным текстом, как и LIKE, но они предоставляют мощный набор метасимволов‑операторов, позволяющих создавать сложные шаблоны сопоставления. Шаблон regex работает на уровне символов и может сопоставлять буквы, цифры и другие символы, либо по буквальному значению (например, /abc/ будет соответствовать abc), либо по типу класса, например \w будет соответствовать [A‑Aa‑z0‑9_]. Шаблон также может включать логическое or, как abc|xyz, квантификации — ? обозначает ноль или один вхождений предшествующего символа или подстановочного знака (метасимвол .).
В отличие от regex, полнотекстовый поиск не работает с обычным текстом, а разбирает тексты и сегментирует их на слова. Полнотекстовый поиск не пытается найти шаблон в строке, а ищет в наборе слов. Хотя регулярные выражения могут находить и изолировать слова, у них есть естественные ограничения, так как они не могут выполнять простые булевые поиски вроде abc -xyz или работать с морфологией. Некоторые возможности, присутствующие в регулярных выражениях, также доступны в полнотекстовом поиске, например операторы start/end. Некоторые работают иначе. Например, wildcards в regex могут заменять любое количество символов, но в полнотекстовом поиске подстановочные знаки могут расширяться только в пределах слова или могут полностью заменять слово.
Как используются регулярные выражения в Manticore Search?
Регулярные выражения были доступны до настоящего времени как опциональная функция на этапе индексации через
regexp_filter
. Regex можно использовать для преобразования строк, что иначе было бы сложнее реализовать обычными опциями токенизации. Например, лигатуру 'ae' можно заменить на 'a' или заменить шаблон вроде XX" на XX inch.
Начиная с версии 2.7.5 регулярные выражения можно использовать в SELECT‑запросах с помощью функции REGEX() . REGEX() принимает на вход строку, которая может быть получена из строкового атрибута или свойства JSON, а также регулярное выражение, которое будет проверено относительно входных данных. REGEX работает только с значениями атрибутов, её нельзя использовать для полнотекстовых полей.
Зачем нужна функция REGEX, если мы уже можем индексировать тексты в полнотекстовых полях?
Во‑первых, у нас могут быть строки (либо как атрибуты, либо в JSON‑данных), к которым необходимо применить поисковый шаблон, не связанный напрямую с полнотекстовым сопоставлением. Например, метаданные могут содержать некоторые коды, и мы хотим сузить поиск, оставив только записи, где эти коды начинаются с цифры, например
SELECT * FROM myindex WHERE MATCH('something') AND REGEX(json_attr.code, "^\d\w+")
Еще одна причина — в настоящее время текстовые данные из JSON‑атрибутов не индексируются как полнотекстовые. Если нам нужно выполнить над некоторыми строковыми свойствами более сложное сопоставление, чем простое сравнение, нам придётся перенести их в полнотекстовое поле (и использовать ZONEs для ограничения сопоставления определёнными метками) или в несколько полнотекстовых полей (что может стать проблемой, если количество таких свойств варьируется).
Например, метаданные продукта, заключённые в объект JSON, могут содержать свойство со списком совместимых устройств этого продукта. С помощью REGEX мы можем создать шаблон, который будет находить нужный нам продукт или даже серию этого продукта:
SELECT * FROM myindex WHERE MATCH('red case') AND REGEX(json_attr.compatible_devices, "Galaxy S[7|8|9]")
В некоторых случаях REGEX() может быть незаменима. Дайте нам знать, если вы сочтёте её полезной!