在本文中,我们将讨论如何快速开始使用 Docker 配合 Manticore Search。
安装和运行
官方 Docker 镜像托管在
https://hub.docker.com/r/manticoresearch/manticore/
。
要启动 Manticore Search,您只需运行:
$ docker run --name manticore -p 9306:9306 -d manticoresearch/manticore
Docker 配方托管在 github ,供那些希望扩展现有镜像的用户使用。
Manticore Search 容器没有持久化存储,如果容器停止,所有更改都会丢失。一个简单的方法是将几个文件夹挂载到本地机器上。
我们希望持久化的文件夹是:
- /etc/sphinxsearch - sphinx.conf 的位置
- /var/lib/manticore/data - 用于索引文件
- /var/lib/manticore/log - 用于日志文件
我们在主目录中考虑一个 manticore/ 文件夹,其中我们将创建 etc/、data/ 和 logs/ 文件夹,并在 ~/manticore/etc/ 中添加一个有效的 sphinx.conf。我们可以使用配方存储库中包含的
sphinx.conf
。
我们在运行命令中添加挂载:
$ docker run --name manticore -v ~/manticore/etc/:/etc/sphinxsearch/ -v ~/manticore/data/:/var/lib/manticore/data -v ~/manticore/logs/:/var/lib/manticore/log -p 9306:9306 -d manticoresearch/manticore
可以通过以下方式停止容器:
$ docker stop manticore
Docker 镜像还包含 indexer 和 indextoo 工具,这些工具可以使用 Docker 的 exec 命令运行:
$ docker exec -it manticore indexer --all --rotate
运行查询
连接并进行一些测试的简单方法是使用 SphinxQL 协议。为此,您需要一个 mysql 命令行客户端。
虽然它实现了 MySQL 协议,但 SphinxQL 并不完全兼容 MySQL 语法。有一些特定的扩展,比如 MATCH 子句(Manticore 最强大的功能之一)或 WITHIN GROUP BY,以及许多在 MySQL 中可用的函数未实现(或仅实现为 dummy 以允许与 MySQL 连接器兼容),或者尚未支持的索引之间的 JOIN。
首先,让我们连接到 Manticore Search 并查看可用的索引:
$ mysql -P9306 -h0
mysql> SHOW TABLES;
+-------+-------------+
| Index | Type |
+-------+-------------+
| dist1 | distributed |
| testrt| rt |
+-------+-------------+
2 rows in set (0.00 sec)
现在让我们查看我们的 RT 索引:
mysql> DESCRIBE testrt;
+---------+--------+
| Field | Type |
+---------+--------+
| id | bigint |
| title | field |
| content | field |
| gid | uint |
+---------+--------+
4 rows in set (0.00 sec)
由于 RT 索引最初是空的,让我们先向其中添加一些数据
mysql> INSERT INTO testrt VALUES(1,'List of HP business laptops','Elitebook Probook',10);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(2,'List of Dell business laptops','Latitude Precision Vostro',10);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(3,'List of Dell gaming laptops','Inspirion Alienware',20);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(4,'Lenovo laptops list','Yoga IdeaPad',30);
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO testrt VALUES(5,'List of ASUS ultrabooks and laptops','Zenbook Vivobook',30);
Query OK, 1 row affected (0.01 sec)
现在我们有一些数据,可以执行一些查询。
全文搜索使用特殊的 MATCH 子句完成,这是主要的工具。
mysql> SELECT * FROM testrt WHERE MATCH('list of laptops');
+------+------+
| id | gid |
+------+------+
| 1 | 10 |
| 2 | 10 |
| 3 | 20 |
| 5 | 30 |
+------+------+
4 rows in set (0.00 sec)
如您在结果集中看到的,我们只能获取回文档 ID 和属性。全文字段的值不会返回,因为文本仅被索引,未存储,而且无法重建原始文本。
现在让我们添加一些过滤和更多排序:
mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCG('list of laptops') AND gid>10 ORDER BY WEIGHT() DESC,gid DESC;
+------+------+----------+
| id | gid | weight() |
+------+------+----------+
| 5 | 30 | 2334 |
| 3 | 20 | 2334 |
+------+------+----------+
2 rows in set (0.00 sec)
WEIGHT() 函数返回计算出的匹配分数。如果没有指定排序,结果将按 WEIGHT() 提供的分数降序排列。在这个例子中,我们首先按权重排序,然后按整数属性排序。
上面的搜索执行简单的匹配,其中所有单词都需要存在。但我们可以做得更多(这只是个简单示例):
mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCH('"list of business laptops"/3');
+------+------+----------+
| id | gid | weight() |
+------+------+----------+
| 1 | 10 | 2397 |
| 2 | 10 | 2397 |
| 3 | 20 | 2375 |
| 5 | 30 | 2375 |
+------+------+----------+
4 rows in set (0.00 sec)
mysql> SHOW META;
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| total | 4 |
| total_found | 4 |
| time | 0.000 |
| keyword[0] | list |
| docs[0] | 5 |
| hits[0] | 5 |
| keyword[1] | of |
| docs[1] | 4 |
| hits[1] | 4 |
| keyword[2] | business |
| docs[2] | 2 |
| hits[2] | 2 |
| keyword[3] | laptops |
| docs[3] | 5 |
| hits[3] | 5 |
+---------------+----------+
15 rows in set (0.00 sec)
在这里我们搜索 4 个单词,但即使只找到其中 3 个单词(4 个中的 3 个)也可以匹配。搜索将首先对包含所有单词的文档进行更高排名。我们还添加了 SHOW META 命令。SHOW META 返回有关之前执行查询的信息,即找到的记录数(在 total_found 中)、执行时间(在 time 中)以及搜索关键字的统计信息。
使用普通索引
与 RT 不同,普通索引也需要为其配置一个源。在我们的示例中,我们使用 MySQL 源。
在您的 sphinx.conf 中添加:
source src1
{
type = mysql
sql_host = 172.17.0.1
sql_user = test
sql_pass =
sql_db = test
sql_port = 3306 # optional, default is 3306
sql_query_pre = SET NAMES utf8
sql_query = \
SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
FROM documents
sql_attr_uint = group_id
sql_attr_timestamp = date_added
}
index test1
{
source = src1
path = /var/lib/manticore/data/test1
min_word_len = 1
}
在这个示例中,我们假设 MySQL 在本地主机上运行,但 Manticore Search 在 Docker 容器内运行,因此我们需要使用 '172.17.0.1',这是 Docker 主机的静态 IP 地址。有关更多详细信息,请参阅 Docker 文档。您还需要相应地调整 MySQL 凭据。
然后我们查看 sql_query,这是获取数据的查询
sql_query = \
SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
FROM documents
我们将使用这个 SQL 片段在 MySQL 中创建我们的测试表:
DROP TABLE IF EXISTS test.documents;
CREATE TABLE test.documents
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
group_id INTEGER NOT NULL,
date_added DATETIME NOT NULL,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL
);
INSERT INTO test.documents ( id, group_id, date_added, title, content ) VALUES
( 1, 1, NOW(), 'test one', 'this is my test document number one. also checking search within phrases.' ),
( 2, 1, NOW(), 'test two', 'this is my test document number two' ),
( 3, 2, NOW(), 'another doc', 'this is another group' ),
( 4, 2, NOW(), 'doc number four', 'this is to test groups' );
如果您想使用另一个表,请记住结果集中的第一列必须是无符号唯一整数 - 对于大多数情况,这是表的主键 id。
如果没有指定,其余列将作为全文字段进行索引。需要作为属性使用的列需要声明。在我们的示例中 group_id 和 date_added 是属性:
sql_attr_uint = group_id
sql_attr_timestamp = date_added
一旦我们有了这个设置,就可以运行索引过程:
$ docker exec -it manticore indexer test1 --rotate
using config file '/etc/sphinxsearch/sphinx.conf'...
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 193 bytes
total 0.015 sec, 12335 bytes/sec, 255.65 docs/sec
total 4 reads, 0.000 sec, 8.1 kb/call avg, 0.0 msec/call avg
total 12 writes, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg
索引已创建并准备使用:
mysql> SHOW TABLES;
+-------+-------------+
| Index | Type |
+-------+-------------+
| dist1 | distributed |
| rt | rt |
| test1 | local |
+-------+-------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM test1;
+------+----------+------------+
| id | group_id | date_added |
+------+----------+------------+
| 1 | 1 | 1507904567 |
| 2 | 1 | 1507904567 |
| 3 | 2 | 1507904567 |
| 4 | 2 | 1507904567 |
+------+----------+------------+
4 rows in set (0.00 sec)
对一个应匹配两个术语但不匹配另一个术语的搜索进行快速测试:
mysql> SELECT * FROM test1 WHERE MATCH('test document -one');
+------+----------+------------+-------+
| id | group_id | date_added | tag |
+------+----------+------------+-------+
| 2 | 1 | 1519040667 | 2,4,6 |
+------+----------+------------+-------+
1 row in set (0.00 sec)