Рассмотрим этот пример сложного запроса:
"hello world" @title "example program"~5 @body python -(php|perl) @* code
Полное значение этого поиска:
- Найти слова 'hello' и 'world' рядом друг с другом в любом поле документа;
- Кроме того, в том же документе должны содержаться слова 'example' и 'program' в поле заголовка, с не более чем 5 словами между ними (не включая 5); (например, "example PHP program" подойдет, а "example script to introduce outside data into the correct context for your program" — нет, так как между двумя терминами 5 или более слов)
- Более того, в том же документе должно быть слово 'python' в поле body, при этом исключая 'php' или 'perl';
- Наконец, в том же документе должно содержаться слово 'code' в любом поле.
Оператор OR имеет приоритет над AND, поэтому "looking for cat | dog | mouse" означает "looking for (cat | dog | mouse)", а не "(looking for cat) | dog | mouse".
Чтобы понять, как будет выполняться запрос, Manticore Search предоставляет инструменты профилирования запросов для изучения дерева запроса, сгенерированного выражением запроса.
Чтобы включить профилирование полнотекстового запроса с помощью SQL-запроса, необходимо активировать его перед выполнением нужного запроса:
SET profiling =1;
SELECT * FROM test WHERE MATCH('@title abc* @body hey');
Чтобы просмотреть дерево запроса, выполните команду SHOW PLAN сразу после выполнения запроса:
SHOW PLAN;
Эта команда вернет структуру выполненного запроса. Имейте в виду, что 3 оператора — SET profiling, сам запрос и SHOW — должны выполняться в одной сессии.
При использовании протокола HTTP JSON можно просто включить "profile":true, чтобы получить в ответе структуру дерева полнотекстового запроса.
{
"table":"test",
"profile":true,
"query":
{
"match_phrase": { "_all" : "had grown quite" }
}
}
В ответе будет объект profile, содержащий член query.
Свойство query содержит преобразованное дерево полнотекстового запроса. Каждый узел состоит из:
type: тип узла, который может быть AND, OR, PHRASE, KEYWORD и т.д.description: поддерево запроса для этого узла, представленное в виде строки (в форматеSHOW PLAN)children: дочерние узлы, если естьmax_field_pos: максимальная позиция в поле
У узла ключевого слова дополнительно будут:
word: преобразованное ключевое слово.querypos: позиция этого ключевого слова в запросе.excluded: ключевое слово исключено из запроса.expanded: ключевое слово добавлено расширением префикса.field_start: ключевое слово должно появиться в начале поля.field_end: ключевое слово должно появиться в конце поля.boost: IDF ключевого слова будет умножен на это значение.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
SET profiling=1;
SELECT * FROM test WHERE MATCH('@title abc* @body hey');
SHOW PLAN \G*************************** 1\. row ***************************
Variable: transformed_tree
Value: AND(
OR(fields=(title), KEYWORD(abcx, querypos=1, expanded), KEYWORD(abcm, querypos=1, expanded)),
AND(fields=(body), KEYWORD(hey, querypos=2)))
1 row in set (0.00 sec)В некоторых случаях оцениваемое дерево запроса может значительно отличаться от исходного из-за расширений и других преобразований.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
SET profiling=1;
SELECT id FROM forum WHERE MATCH('@title way* @content hey') LIMIT 1;
SHOW PLAN;Query OK, 0 rows affected (0.00 sec)
+--------+
| id |
+--------+
| 711651 |
+--------+
1 row in set (0.04 sec)
+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable | Value |
+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| transformed_tree | AND(
OR(
OR(
AND(fields=(title), KEYWORD(wayne, querypos=1, expanded)),
OR(
AND(fields=(title), KEYWORD(ways, querypos=1, expanded)),
AND(fields=(title), KEYWORD(wayyy, querypos=1, expanded)))),
AND(fields=(title), KEYWORD(way, querypos=1, expanded)),
OR(fields=(title), KEYWORD(way*, querypos=1, expanded))),
AND(fields=(content), KEYWORD(hey, querypos=2))) |
+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)SQL-оператор EXPLAIN QUERY позволяет отобразить дерево выполнения для заданного полнотекстового запроса без фактического выполнения поискового запроса по таблице.
- SQL
EXPLAIN QUERY index_base '@title running @body dog'\G EXPLAIN QUERY index_base '@title running @body dog'\G
*************************** 1\. row ***************************
Variable: transformed_tree
Value: AND(
OR(
AND(fields=(title), KEYWORD(run, querypos=1, morphed)),
AND(fields=(title), KEYWORD(running, querypos=1, morphed))))
AND(fields=(body), KEYWORD(dog, querypos=2, morphed)))EXPLAIN QUERY ... option format=dot позволяет отобразить дерево выполнения заданного полнотекстового запроса в иерархическом формате, подходящем для визуализации с помощью существующих инструментов, таких как https://dreampuf.github.io/GraphvizOnline:

- SQL
EXPLAIN QUERY tbl 'i me' option format=dot\GEXPLAIN QUERY tbl 'i me' option format=dot\G
*************************** 1. row ***************************
Variable: transformed_tree
Value: digraph "transformed_tree"
{
0 [shape=record,style=filled,bgcolor="lightgrey" label="AND"]
0 -> 1
1 [shape=record,style=filled,bgcolor="lightgrey" label="AND"]
1 -> 2
2 [shape=record label="i | { querypos=1 }"]
0 -> 3
3 [shape=record,style=filled,bgcolor="lightgrey" label="AND"]
3 -> 4
4 [shape=record label="me | { querypos=2 }"]
}При использовании ранжировщика выражений можно вывести значения вычисленных факторов с помощью функции PACKEDFACTORS().
Функция возвращает:
- Значения факторов на уровне документа (таких как bm25, field_mask, doc_word_count)
- Список каждого поля, которое сгенерировало совпадение (включая lcs, hit_count, word_count, sum_idf, min_hit_pos и т.д.)
- Список каждого ключевого слова из запроса вместе с их значениями tf и idf
Эти значения можно использовать для понимания, почему определённые документы получают более низкие или высокие оценки в поиске, или для уточнения существующего выражения ранжирования.
- SQL
SELECT id, PACKEDFACTORS() FROM test1 WHERE MATCH('test one') OPTION ranker=expr('1')\G id: 1
packedfactors(): bm25=569, bm25a=0.617197, field_mask=2, doc_word_count=2,
field1=(lcs=1, hit_count=2, word_count=2, tf_idf=0.152356,
min_idf=-0.062982, max_idf=0.215338, sum_idf=0.152356, min_hit_pos=4,
min_best_span_pos=4, exact_hit=0, max_window_hits=1, min_gaps=2,
exact_order=1, lccs=1, wlccs=0.215338, atc=-0.003974),
word0=(tf=1, idf=-0.062982),
word1=(tf=1, idf=0.215338)
1 row in set (0.00 sec)