在这篇文章中,我们将讨论如何快速开始使用 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 并不是 100% 兼容 MySQL 语法。有一些特定的扩展,例如 MATCH 子句 [Manticore 中最强大的功能] 或 WITHIN GROUP BY,以及许多在 MySQL 中可用的函数未实现(或者它们只是虚拟的,以允许与 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)
快速测试一个搜索,应该匹配 2 个术语,但不匹配另一个:
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)