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

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

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

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

Обычный способ выполнения поисков заключается в том, чтобы хранить документы, которые мы хотим искать, и выполнять запросы к ним. Однако есть случаи, когда мы хотим применить запрос к входящему новому документу, чтобы сигнализировать о совпадении. Есть несколько сценариев, когда это необходимо. Например, система мониторинга не просто собирает данные, но также желательно уведомлять пользователя о различных событиях. Это может быть достижение некоторого порога для метрики или определенного значения, которое появляется в отслеживаемых данных. Другой аналогичный случай — агрегирование новостей. Вы можете уведомлять пользователя о любых свежих новостях, но пользователь может захотеть получать уведомления только по определенным категориям или темам. Двигаясь дальше, они могут быть заинтересованы только в определенных "ключевых словах".

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

Обходное решение было возможно с использованием индекса в реальном времени, в который добавлялись только новые документы, запросы проверялись, и индекс в реальном времени обрезался. Но это было далеко от решения. Наконец, мы добавляем эту функциональность в 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)

Идентификатор документа поддерживает автоинкремент, при выполнении вставок вам не нужно генерировать идентификатор, как для обычных индексов в реальном времени. Вставка нового запроса требует обязательного текстового поля '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 как docs_json. Также по умолчанию набор результатов содержит только идентификатор запроса, но мы можем использовать опцию 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 предоставляет информацию о выполненной функции, такую как время выполнения, количество запросов и совпавших документов, общее количество сохраненных запросов.
Когда 'verbose' установлен в CALL PQ, отображается дополнительная информация, такая как время, затраченное на каждый запрос.

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