⚠️ Эта страница автоматически переведена, и перевод может быть несовершенным.
blog-post

Introduction to full-text operators and basic search

В этом учебном пособии мы рассмотрим операторы полнотекстового поиска, доступные в Manticore Search.

Введение в операторы полнотекстового поиска и базовый поиск

Все операции поиска в Manticore Search основаны на стандартных булевых операторах (AND, OR, NOT), которые можно использовать в комбинации и произвольном порядке для объединения или исключения ключевых слов в поиске более релевантных результатов.

Оператор полнотекстового поиска по умолчанию и самый простой — это AND, который подразумевается, когда вы просто перечисляете несколько слов в поиске.

Full-Text-Operators-in-Manticore_ANDAND — это оператор по умолчанию, с помощью которого запрос fast slow вернет документы, содержащие оба термина: 'fast' и 'slow'. Если один термин присутствует в документе, а другой — нет, документ не будет включен в результирующий список.
По умолчанию слова будут искаться во всех доступных полнотекстовых полях.

SELECT * FROM testrt WHERE MATCH('fast slow');

Full-Text-Operators-in-Manticore_OROR используется для соответствия любому термину (или обоим). Термины должны быть разделены вертикальной чертой, например, 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 NOT гарантирует, что термин, отмеченный - или !, отсутствует в результатах. Любые документы, содержащие такой термин, будут исключены. Например, fast !slow найдет документы с fast, если только в них нет slow. Будьте осторожны, используя его, пытаясь сократить поиск, так как это может сделать его слишком специфичным и исключить хорошие документы.

SELECT * FROM testrt WHERE MATCH('find !slow');

SELECT * FROM testrt WHERE MATCH('find -slow');

MAYBEMAYBE — это специальный оператор, который работает как 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)

Чтобы продемонстрировать оператор PARAGRAPH, используем следующий поиск:

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‑теги

Если добавить оператор PARAGRAPH, останется только документ, в котором поисковые термины найдены в единственном теге.

Более общие операторы — 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">

Вы можете узнать больше о полнотекстовом сопоставлении, попробовав наш "Вводный курс по операторам полнотекстового поиска" интерактивный курс , который включает командную строку для более простого обучения.

Установить Manticore Search

Установить Manticore Search