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

Percolate Queries

Одна из давно запрашиваемых функций теперь доступна в последней версии кода: запросы перколяции.

Если вы хотите пройти интерактивный курс, перейдите сюда .

Запросы перколяции также известны как постоянные запросы, перспективный поиск, маршрутизация документов, поиск в обратном направлении или обратный поиск.

Обычный способ выполнения поиска заключается в хранении документов, которые мы хотим искать, и выполнении запросов к ним. Однако бывают случаи, когда мы хотим применить запрос к поступающему новому документу, чтобы определить совпадение. Существуют сценарии, где это необходимо. Например, система мониторинга не только собирает данные, но и должна уведомлять пользователя о различных событиях. Это может быть достижение некоторого порога метрики или появление определённого значения в мониторируемых данных. Аналогичный случай — агрегирование новостей. Вы можете уведомлять пользователя о любой свежей новости, но пользователь может захотеть получать уведомления только по определённым категориям или темам. Более того, его могут интересовать только определённые «ключевые слова».

Здесь традиционный поиск оказывается неуместным, поскольку он предполагает выполнение желаемого поиска по всей коллекции, что умножается на количество пользователей, и в итоге у нас появляется множество запросов, работающих по всей коллекции, что создает значительную дополнительную нагрузку. Чтобы решить эту проблему, возникла идея вместо этого хранить запросы и проверять их по поступающему новому документу или пакету документов.

Обходное решение было возможно с использованием индекса реального времени, в который добавлялись только новые документы, запросы проверялись, а RT обрезался. Но это было далеко не идеальное решение. Наконец, мы добавляем эту функциональность в Manticore Search (и, соответственно, для всех, кто обновляется с Sphinx Search).

Для хранения запросов используется новый тип индекса, основанный на индексе реального времени. Индекс percolate позволяет добавлять запросы, просматривать их или удалять.

Сопоставление запросов осуществляется с помощью нового оператора, который принимает в качестве входных данных документ или список документов и возвращает, какие запросы получили совпадение.

Обратите внимание, что индекс 'percolate' не является заменой существующего индекса, он не хранит документы. В обычном случае документы вставляются в индекс, как и прежде. Запросы перколяции могут выполняться либо после вставки тем же рабочим процессом, либо другим процессом, независимым от процесса вставки (который может запускаться cron‑задачей или срабатывать при вставках). Последний вариант предпочтительнее, чтобы PQ не задерживали подтверждение (для конечного пользователя) вставки, но это зависит от рабочего процесса приложения.

Хранение запросов перколяции

Как указано выше, запросы перколяции хранятся в специальном индексе реального времени, определённом как тип percolate.

Простой индекс PQ требует лишь определения типа и пути:

index pq {
    type = percolate
    path = /var/lib/sphinxsearch/pq
}

Чтобы сделать его доступным, просто выполните команду RELOAD INDEXES :

MySQL [(none)]> RELOAD INDEXES; SHOW TABLES LIKE 'pq';
Query OK, 0 rows affected (0.00 sec)

+-------+-----------+
| Index | Type      |
+-------+-----------+
| pq    | percolate |
+-------+-----------+
1 row in set (0.00 sec)

Идентификатор документа поддерживает автоинкремент; при вставках вам не нужно генерировать id, как для обычных RT‑индексов. Вставка нового запроса требует обязательного текстового поля 'query', которое содержит выражение полнотекстового поиска.

MySQL [(none)]> INSERT INTO pq(query) VALUES('catch me');
Query OK, 1 rows affected (0.00 sec)

MySQL [(none)]> SELECT * FROM pq;
+------+----------+------+---------+
| UID  | Query    | Tags | Filters |
+------+----------+------+---------+
|    1 | catch me |      |         |
+------+----------+------+---------+
1 row in set (0.00 sec)

Существует 2 необязательных атрибута со специальным использованием.

Первый — 'tags', который поддерживает набор строк (подобно строковому MVA). Теги могут использоваться для фильтрации PQ при выполнении SELECT или DELETE, но они не участвуют в перколяционных поисках.

MySQL [(none)]> insert into pq(query,tags) values('catch me if','tag1');
Query OK, 1 rows affected (0.00 sec)

MySQL [(none)]> SELECT * FROM pq WHEREtags='tag1';
+------+-------------+------+---------+
| UID  | Query       | Tags | Filters |
+------+-------------+------+---------+
|    2 | catch me if | tag1 |         |
+------+-------------+------+---------+
2 rows in set (0.00 sec)

Второй — 'filters', содержащий дополнительные правила запросов, в которых можно хранить фильтрацию атрибутов в формате SphinxQL. Атрибуты, используемые здесь, должны быть объявлены в конфигурации индекса так же, как атрибуты в RT‑индексе. Чтобы включить новый атрибут, можно просто использовать ALTER RTINDEX RECONFIGURE.

index pq {
    type = percolate
     path = /var/lib/sphinxsearch/pq
     rt_attr_uint = catId
}

MySQL [(none)]> ALTER RTINDEX pq RECONFIGURE;
Query OK, 0 rows affected (0.00 sec)

MySQL [(none)]> INSERT INTO pq(query,tags,filters) VALUES('catch me','tag2,tag1','catId=10');
Query OK, 1 rows affected (0.00 sec)

MySQL [(none)]> select * from pq;
+------+-------------+-----------+-----------+
| UID  | Query       | Tags      | Filters   |
+------+-------------+-----------+-----------+
|    3 | catch me    |           |           |
|    4 | catch me if | tag1      |           |
|    5 | catch me    | tag2,tag1 |  catid=10 |
+------+-------------+-----------+-----------+
3 rows in set (0.00 sec)

Если мы хотим включить поиск текста по отдельным полям, необходимо определить полнотекстовые поля в конфигурации индекса и выполнить переустановку.

index pq {
    type = percolate
    path = /var/lib/sphinxsearch/pq
    rt_field = subject
    rt_field = content
    rt_attr_uint = catId
}

MySQL [(none)]>  ALTER RTINDEX pq RECONFIGURE;
Query OK, 0 rows affected (0.00 sec)

MySQL [(none)]> INSERT INTO pq(query,tags,filters) VALUES('@subject match by field','tag2,tag3','catId=10');
Query OK, 1 rows affected (0.00 sec)

MySQL [(none)]> INSERT INTO pq(query,tags,filters) VALUES('@subject  match by field','tag2,tag3','catId=20');
Query OK, 1 rows affected (0.00 sec)

Выполнение запросов перколяции

Функцию CALL PQ можно использовать с одним индексом перколяции (пока), который указывается в первом параметре функции. Второй параметр, обязательный, содержит документ или список документов. Передаваемый документ(ы) может быть обычным текстом или объектом JSON. Объект JSON позволяет передавать несколько текстовых полей, поэтому возможны совпадения по отдельным полям, а также атрибуты, проверяемые по выражению, определённому в атрибуте 'filters' запроса перколяции. Это означает, что запрос может быть не только выражением полнотекстового совпадения, но также может включать фильтры атрибутов, позволяющие более сложное сопоставление (например, кто‑то ищет определённые ключевые слова, но хочет получать уведомления только для определённых типов или категорий статей).

По умолчанию CALL PQ ожидает документы в формате JSON, поэтому для выполнения самого простого примера нам нужно передать 0 as docs_json. Кроме того, набор результатов по умолчанию содержит только ID запроса, но мы можем использовать опцию query, чтобы отобразить всю сохранённую информацию.

MySQL [(none)]> CALL PQ('pq','catch me',0 AS docs_json,1 AS query);
+------+----------+------+---------+
| UID  | Query    | Tags | Filters |
+------+----------+------+---------+
|    6 | catch me |      |         |
+------+----------+------+---------+
1 row in set (0.00 sec)

Чтобы выполнить сопоставление по отдельным полям или дополнительную фильтрацию атрибутов, нам нужно передать документы в виде объекта JSON.

MySQL [(none)]> CALL PQ('pq','{"subject":"expect to match by field","content":"here is some content","catid":20}',1 AS query);
+------+--------------------------+-----------+-----------+
| UID  | Query                    | Tags      | Filters   |
+------+--------------------------+-----------+-----------+
|   10 | @subject  match by field | tag2,tag3 |  catid=20 |
+------+--------------------------+-----------+-----------+
1 row in set (0.00 sec)

CALL PQ имеет ещё 2 параметра выполнения: опция 'docs' полезна, когда на вход подаётся более одного документа, так как она указывает, какой документ совпал с поиском (начиная с индекса 1).

MySQL [(none)]> CALL PQ('pq',('catch me if can','catch me'),0 AS docs_json,1 AS docs,1 AS verbose);
+------+-----------+-------------+------+---------+
| UID  | Documents | Query       | Tags | Filters |
+------+-----------+-------------+------+---------+
|    6 | 1,2       | catch me    |      |         |
|    7 | 1         | catch me if | tag1 |         |
+------+-----------+-------------+------+---------+
2 rows in set (0.00 sec)

При выполнении CALL PQ команда SHOW META предоставляет информацию о выполненной функции, такую как время выполнения, количество запросов и совпавший документ, общее число сохранённых запросов.
Когда в CALL PQ установлен параметр 'verbose', отображается дополнительная информация, например время, затраченное на каждый запрос.

MySQL [(none)]> SHOW META;
+-------------------------+-----------+
| Name                    | Value     |
+-------------------------+-----------+
| Total                   | 0.000 sec |
| Setup                   | 0.000 sec |
| Queries matched         | 2         |
| Document matches        | 2         |
| Total queries stored    | 6         |
| Term only queries       | 6         |
| Fast rejected queries   | 3         |
| Time per query          | 32, 21    |
| Time of matched queries | 53        |
+-------------------------+-----------+
9 rows in set (0.00 sec)

Обратная связь

Поскольку это новая функция, добавленная в Manticore, открывающая новые сценарии использования Manticore Search, мы приглашаем всех протестировать её и предоставить любые отзывы. Тем временем мы продолжаем работу над ней, осталось несколько вещей, прежде чем мы сможем назвать её готовой к продакшн. Мы будем благодарны за любую помощь в тестировании.

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

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