В этом учебном пособии мы рассмотрим операторы полнотекстового поиска, доступные в Manticore Search.
Введение в операторы полнотекстового поиска и базовый поиск
Все операции поиска в Manticore Search основаны на стандартных булевых операторах (AND, OR, NOT), которые могут использоваться в комбинации и свободном порядке для объединения или исключения ключевых слов в поиске более релевантных результатов.
По умолчанию и самый простой оператор полнотекстового поиска - это AND, который подразумевается, когда вы просто перечисляете несколько слов в поиске.
AND - это оператор по умолчанию, с помощью которого запрос fast slow вернет документы, содержащие оба термина: 'fast' и 'slow'. Если один термин присутствует в документе, а другой - нет, документ не будет включен в результирующий список.
По умолчанию слова будут искаться во всех доступных полнотекстовых полях.
SELECT * FROM testrt WHERE MATCH('fast slow');
OR используется для совпадения с любым термином (или обоими). Термины должны быть разделены вертикальной чертой, например, fast | slow. Он найдет документы с fast или slow.
SELECT * FROM testrt WHERE MATCH('fast | slow');
Оператор OR имеет более высокий приоритет, чем AND, поэтому запрос 'find me fast|slow' может быть интерпретирован как 'найди мне (fast|slow)':
SELECT * FROM testrt WHERE MATCH('find me fast | slow');
NOT гарантирует, что термин, отмеченный - или !, отсутствует в результатах. Любые документы, содержащие такой термин, будут исключены. Например, fast !slow найдет документы с fast, если только в них нет slow. Будьте осторожны, используя его, пытаясь сократить поиск, так как это может стать слишком специфичным и исключить хорошие документы.
SELECT * FROM testrt WHERE MATCH('find !slow');
SELECT * FROM testrt WHERE MATCH('find -slow');
MAYBE - это специальный оператор, который работает как OR, но требует, чтобы левый термин всегда присутствовал в результатах, в то время как правый термин является необязательным. Но когда оба термина присутствуют, документ получит более высокий рейтинг в поиске. Например, fast MAYBE slow найдет документы с fast или slow, но документы, содержащие оба термина, будут иметь более высокий балл.
SELECT * FROM testrt WHERE MATCH('find MAYBE slow');
Примеры использования
Давайте подключимся к Manticore с помощью клиента mysql:
# mysql -P9306 -h0
Для булевых поисков можно использовать оператор OR |:
MySQL [(none)]> select * from testrt where match('find | me fast');
+------+------+------------------------+----------------+
| id | gid | title | content |
+------+------+------------------------+----------------+
| 1 | 1 | find me | fast and quick|
| 2 | 1 | find me fast | quick |
| 6 | 1 | find me fast now | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+----------------+
4 rows in set (0.00 sec)
Оператор OR имеет более высокий приоритет, чем AND, запрос find me fast|slow интерпретируется как find me (fast|slow):
MySQL [(none)]> SELECT * FROM testrt WHERE MATCH('find me fast|slow');
+------+------+------------------------+----------------+
| id | gid | title | content |
+------+------+------------------------+----------------+
| 1 | 1 | find me | fast and quick|
| 2 | 1 | find me fast | quick |
| 6 | 1 | find me fast now | quick |
| 3 | 1 | find me slow | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+----------------+
5 rows in set (0.00 sec)
Для отрицаний оператор NOT может быть указан как - или !:
MySQL [(none)]> select * from testrt where match('find me -fast');
+------+------+--------------+---------+
| id | gid | title | content |
+------+------+--------------+---------+
| 3 | 1 | find me slow | quick |
+------+------+--------------+---------+
1 row in set (0.00 sec)
Следует отметить, что полнофункциональные отрицательные запросы по умолчанию не поддерживаются в Manticore, и невозможно выполнить просто -fast (это станет возможным с версии 3.5.2).
Другим базовым оператором является MAYBE. Термин, определенный с помощью MAYBE, может присутствовать или отсутствовать в документах. Если он присутствует, это повлияет на рейтинг, и документы, содержащие его, будут оценены выше.
MySQL [(none)]> select * from testrt where match('find me MAYBE slow');
+------+------+------------------------+----------------+
| id | gid | title | content |
+------+------+------------------------+----------------+
| 3 | 1 | find me slow | quick |
| 1 | 1 | find me | fast and quick|
| 2 | 1 | find me fast | quick |
| 5 | 1 | find me quick and fast | quick |
| 6 | 1 | find me fast now | quick |
+------+------+------------------------+----------------+
5 rows in set (0.00 sec)
Оператор поля
Если мы хотим ограничить поиск только определенным полем, можно использовать оператор '@':
mysql> select * from testrt where match('@title find me fast');
+------+------+------------------------+---------+
| id | gid | title | content |
+------+------+------------------------+---------+
| 2 | 1 | find me fast | quick |
| 6 | 1 | find me fast now | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+---------+
3 rows in set (0.00 sec)
Мы также можем указать несколько полей, чтобы ограничить поиск:
mysql> select * from testrt where match('@(title,content) find me fast');
+------+------+------------------------+----------------+
| id | gid | title | content |
+------+------+------------------------+----------------+
| 1 | 1 | find me | fast and quick |
| 2 | 1 | find me fast | quick |
| 6 | 1 | find me fast now | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+----------------+
4 rows in set (0.00 sec)
Оператор поля также может быть использован для ограничения поиска только на первые x слов. Например:
mysql> select * from testrt where match('@title lazy dog');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
4 rows in set (0.00 sec)
Однако, если мы ищем только в первых 5 словах, мы ничего не получаем:
mysql> select * from testrt where match('@title[5] lazy dog');
Empty set (0.00 sec)
В некоторых ситуациях поиск может выполняться по нескольким индексам, которые могут не иметь одинаковых полнотекстовых полей.
По умолчанию указание поля, которого нет в индексе, приведет к ошибке запроса. Чтобы обойти это, можно использовать специальный оператор @@relaxed:
mysql> select * from testrt where match('@(title,keywords) lazy dog');<br></br>ERROR 1064 (42000): index testrt: query error: no field 'keywords' found in schema
mysql> select * from testrt where match('@@relaxed @(title,keywords) lazy dog');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
3 rows in set, 1 warning (0.01 sec)
Неопределенный поиск
Неопределенное соответствие позволяет сопоставлять только некоторые слова из строки запроса, например:
mysql> select * from testrt where match('"fox bird lazy dog"/3');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
3 rows in set (0.00 sec)
В этом случае мы используем оператор QUORUM и указываем, что допустимо совпадение только с 3 из слов. Поиск с /1 эквивалентен булевому поиску OR, в то время как поиск с /N, где N - это количество входных слов, эквивалентен поиску AND.
Вместо абсолютного числа вы также можете указать число от 0.0 до 1.0 (что соответствует 0% и 100%), и Manticore будет сопоставлять только документы с как минимум указанным процентом данных слов. Тот же пример выше также мог быть записан как "fox bird lazy dog"/0.3, и он будет соответствовать документам с как минимум 30% из 4 слов.
mysql> select * from testrt where match('"fox bird lazy dog"/0.3');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
3 rows in set (0.00 sec)
Расширенные операторы
Помимо более простых операторов существует множество расширенных операторов, которые используются реже, но в некоторых случаях могут быть абсолютно необходимы.
Одним из самых часто используемых расширенных операторов является оператор фразы.
Оператор фразы будет соответствовать только в том случае, если заданные слова найдены в точно указанном порядке. Это также ограничит слова, чтобы они были найдены в одном и том же поле:
mysql> SELECT * FROM testrt WHERE MATCH('"quick brown fox"');
+------+------+-------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+-------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+-------------------------------------------------------------------+---------------------------------------+
2 rows in set (0.00 sec)
Более расслабленная версия оператора фразы - это оператор строгого порядка.
Оператор порядка требует, чтобы слова были найдены в точно таком же порядке, как указано, но другие слова принимаются между:
mysql> SELECT * FROM testrt WHERE MATCH('find << me << fast');
+------+------+------------------------+---------+
| id | gid | title | content |
+------+------+------------------------+---------+
| 2 | 1 | find me fast | quick |
| 6 | 1 | find me fast now | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+---------+
3 rows in set (0.00 sec)
Еще одна пара операторов, которые работают с позициями слов, - это операторы начала/конца поля.
Эти операторы ограничат слово, чтобы оно присутствовало в начале или в конце поля.
mysql> SELECT * FROM testrt WHERE MATCH('^find me fast$');
+------+------+------------------------+---------+
| id | gid | title | content |
+------+------+------------------------+---------+
| 2 | 1 | find me fast | quick |
| 5 | 1 | find me quick and fast | quick |
+------+------+------------------------+---------+
2 rows in set (0.00 sec)
Оператор близости похож на оператор AND, но добавляет максимальное расстояние между словами, чтобы они все еще могли считаться совпадением. Рассмотрим этот пример только с оператором AND:
mysql> SELECT * FROM testrt WHERE MATCH('brown fox jumps');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
3 rows in set (0.00 sec)
Наш запрос возвращает 2 результата: один, в котором все слова близки друг к другу, и второй, где одно из слов более удалено.
Если мы хотим соответствовать только в том случае, если слова находятся на определенном расстоянии, мы можем ограничить это с помощью оператора близости:
mysql> SELECT * FROM testrt WHERE MATCH('"brown fox jumps"~5');
+------+------+---------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+---------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+---------------------------------------------+---------------------------------------+
1 row in set (0.00 sec)
Более обобщенная версия оператора близости - это оператор NEAR. В случае близости указывается одно расстояние для набора слов, в то время как оператор NEAR работает с 2 операндами, которые могут быть либо отдельными словами, либо выражениями.
В следующем примере 'brown' и 'fox' должны находиться на расстоянии 2, а 'fox' и 'jumps' на расстоянии 6:
mysql> SELECT * FROM testrt WHERE MATCH('brown NEAR/2 fox NEAR/6 jumps');
+------+------+-------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+-------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+-------------------------------------------------------------------+---------------------------------------+
2 rows in set (0.00 sec)
Запрос пропускает один документ, который не соответствует первому условию NEAR (последнему здесь):
mysql> SELECT * FROM testrt WHERE MATCH('brown NEAR/3 fox NEAR/6 jumps');
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
| 4 | 1 | The quick brown fox jumps over the lazy dog | The five boxing wizards jump quickly |
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
| 8 | 1 | The brown and beautiful fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+----------------------------------------------------------------------------+---------------------------------------+
3 rows in set (0.09 sec)
Вариацией оператора NEAR является NOTNEAR, который совпадает только в том случае, если между операндами есть минимальное расстояние.
mysql> SELECT * FROM testrt WHERE MATCH('"brown fox" NOTNEAR/5 jumps');
+------+------+-------------------------------------------------------------------+---------------------------------------+
| id | gid | title | content |
+------+------+-------------------------------------------------------------------+---------------------------------------+
| 7 | 1 | The quick brown fox take a step back and jumps over the lazy dog | The five boxing wizards jump quickly |
+------+------+-------------------------------------------------------------------+---------------------------------------+
1 row in set (0.00 sec)
Manticore также может обнаруживать предложения в обычных текстах и абзацах в HTML-контенте.
Для индексации предложений необходимо включить опцию index_sp
, в то время как абзацы также требуют html_strip
=1. Рассмотрим следующий пример:
mysql> select * from testrt where match('"the brown fox" jumps')G
*************************** 1. row ***************************
id: 15
gid: 2
title: The brown fox takes a step back. Then it jumps over the lazydog
content:
1 row in set (0.00 sec)
Документ включает 2 предложения, в то время как фраза найдена в первом, 'jumps' есть только во втором предложении.
С помощью оператора SENTENCE мы можем ограничить поиск, чтобы совпадение происходило только в том случае, если операнды находятся в одном предложении:
mysql> select * from testrt where match('"the brown fox" SENTENCE jumps')G
Empty set (0.00 sec)
Мы видим, что документ больше не совпадает. Если мы исправим поисковый запрос так, чтобы все слова были из одного предложения, мы увидим совпадение:
mysql> select * from testrt where match('"the brown fox" SENTENCE back')G<br></br>*************************** 1. row ***************************<br></br>id: 15<br></br>gid: 2<br></br>title: The brown fox takes a step back. Then it jumps over the lazydog<br></br>content:<br></br>1 row in set (0.00 sec)
Чтобы продемонстрировать ПАРАГРАФ, давайте используем следующий поиск:
mysql> select * from testrt where match('Samsung Galaxy');
+------+------+-------------------------------------------------------------------------------------+---------+
| id | gid | title | content |
+------+------+-------------------------------------------------------------------------------------+---------+
| 9 | 2 | <h1>Samsung Galaxy S10</h1>Is a smartphone introduced by Samsung in 2019 | |
| 10 | 2 | <h1>Samsung</h1>Galaxy,Note,A,J | |
+------+------+-------------------------------------------------------------------------------------+---------+
2 rows in set (0.00 sec)
Эти 2 документа имеют разные HTML-теги
Если мы добавим ПАРАГРАФ, останется только документ с найденными поисковыми терминами в одном теге.
Более общие операторы - это ZONE и его вариант ZONESPAN. "zone" - это текст внутри HTML или XML тега.
Теги, которые должны быть учтены для зон, необходимо объявить в настройке index_zones, например, index_zones = h*, th, title.
Например:
mysql> select * from testrt where match('hello world');
+------+------+-------------------------------+---------+
| id | gid | title | content |
+------+------+-------------------------------+---------+
| 12 | 2 | Hello world | |
| 14 | 2 | <h1>Hello world</h1> | |
| 13 | 2 | <h1>Hello</h1> <h1>world</h1> | |
+------+------+-------------------------------+---------+
3 rows in set (0.00 sec)
У нас есть 3 документа, где 'hello' и 'world' найдены в обычном тексте, в разных зонах одного типа или в одной зоне.
mysql> select * from testrt where match('ZONE:h1 hello world');
+------+------+-------------------------------+---------+
| id | gid | title | content |
+------+------+-------------------------------+---------+
| 14 | 2 | <h1>Hello world</h1> | |
| 13 | 2 | <h1>Hello</h1> <h1>world</h1> | |
+------+------+-------------------------------+---------+
2 rows in set (0.00 sec)
В этом случае слова присутствуют в зонах H1, но они не обязаны находиться в одной зоне. Если мы хотим ограничить совпадение одной зоной, мы можем использовать ZONESPAN:
mysql> select * from testrt where match('ZONESPAN:h1 hello world');
+------+------+----------------------+---------+
| id | gid | title | content |
+------+------+----------------------+---------+
| 14 | 2 | <h1>Hello world</h1> | |
+------+------+----------------------+---------+
1 row in set (0.00 sec)
Надеюсь, из этой статьи вы узнали, как работают операторы полнотекстового поиска в Manticore. Если вы ищете практический опыт, чтобы узнать это еще лучше, вы можете попробовать наш интерактивный курс прямо сейчас в вашем браузере.
Интерактивный курс
<img src="Manticore-Full-text-operators-Interactive-course-optimized.webp" alt="img">
Вы можете узнать больше о полнотекстовом совпадении, если попробуете наш "Введение в полнотекстовые операторы" интерактивный курс , который включает командную строку для более легкого обучения.
