查找所有模型和版本中出现零件号开头为 "WIN" 的所有零件
查找描述中有 "lacquer" 或 "paint" 的那些零件
查找描述中有 "black leather" 的所有零件
查找描述中有 "paint" 的所有 2002 J 系列零件
这些搜索中的每个搜索都要求使用长篇的 JOIN 子句或代价高昂的 LIKE 子句,尤其是在 Inventory 表和 Schematic 表十分大时更是如此。而且,复杂的文本搜索完全超出了 MySQL 的能力。要搜索大量文本数据,请考虑构建和使用 Sphinx 索引。
集成 Sphinx 软件
要应用 Sphinx 来解决问题,您必须定义一个或多个数据源以及一个或多个索引。
source 将标识数据库来建立索引,提供验证信息,并且定义查询用以构造每行。数据源可以随意地标识一列或多列作为过滤器,Sphinx 将之称为组。您将使用组来过滤结果。例如,单词描述可能得到 900 个匹配。如果只对特定型号的汽车匹配感兴趣,则可以进一步使用型号组进行过滤。
index 将要求获得数据源(即一组数据行)并定义应当如何为已从数据源中提取出来的数据编目。
您将在 sphinx.conf 文件中定义数据源和索引。Body Parts 的数据源是 MySQL 数据库。清单 5 显示了名为 catalog 的数据源的部分定义 -- 指定连接的数据库以及如何建立连接(主机、套接字、用户和密码)的代码片段。
清单 5. 用于访问 MySQL 数据库的设置
source catalog
{
type = mysql
sql_host = localhost
sql_user = reaper
sql_pass = s3cr3t
sql_db = body_parts
sql_sock = /var/run/mysqld/mysqld.sock
sql_port = 3306
接下来,创建一个查询以生成要被索引的行。通常,将创建 SELECT 子句,可能需要把许多表 JOIN 在一起才能得到行。但这里存在一个问题:搜索型号和年份必须使用 Assembly 表,但是零件号和零件描述只能在 Inventory 表中找到。为此,Sphinx 必须能够把搜索结果与 32 位整型主键绑定在一起。
要获得右侧表单中的数据,需要创建一个视图 -- MySQL V5 中的新结构,它将把来自其他表的列整合到单独的合成虚拟表中。使用视图,各类搜索所需的所有数据都在一个位置,但是活动数据实际上存在于其他表中。清单 6 显示了定义 Catalog 视图的 SQL。
清单 6. Catalog 视图将把数据整合到虚拟表中
CREATE OR REPLACE VIEW Catalog AS
SELECT
Inventory.id,
Inventory.partno,
Inventory.description,
Assembly.id AS assembly,
Model.id AS model
FROM
Assembly, Inventory, Model, Schematic
WHERE
Schematic.partno_id=Inventory.id
AND Schematic.model_id=Model.id
AND Schematic.assembly_id=Assembly.id;
如果用前面所示的表和数据创建名为 body_parts 的数据库,则 Catalog 视图应当类似以下内容:
mysql< use body_parts;
Database changed
mysql< select * from Catalog;
+----+---------+---------------------+----------+-------+
| id | partno | description | assembly | model |
+----+---------+---------------------+----------+-------+
| 6 | 765432 | Bolt | 5 | 1 |
| 8 | ENG088 | Cylinder head | 5 | 1 |
| 1 | WIN408 | Portal window | 3 | 1 |
| 5 | WIN958 | Windshield, front | 3 | 1 |
| 4 | ACC5409 | Cigarette lighter | 7 | 3 |
| 9 | ENG976 | Large cylinder head | 5 | 3 |
| 8 | ENG088 | Cylinder head | 5 | 7 |
| 6 | 765432 | Bolt | 5 | 7 |
+----+---------+---------------------+----------+-------+
8 rows in set (0.00 sec)
在视图中,字段 id 将指回 Inventory 表中的零件条目。partno 和 description 列是要搜索的主要文本,而 assembly 和 model 列用作进一步过滤结果的组。视图就绪后,构造数据源查询就是小事一桩。清单 7 显示了 catalog 数据源定义的其余部分。
清单 7. 查询创建待索引的行
# indexer query
# document_id MUST be the very first field
# document_id MUST be positive (non-zero, non-negative)
# document_id MUST fit into 32 bits
# document_id MUST be unique
sql_query = \
SELECT \
id, partno, description, \
assembly, model \
FROM \
Catalog;
sql_group_column = assembly
sql_group_column = model
# document info query
# ONLY used by search utility to display document information
# MUST be able to fetch document info by its id, therefore
# MUST contain '$id' macro
#
sql_query_info = SELECT * FROM Inventory WHERE id=$id
}
sql_query 必须包括后续查找需要使用的主键,并且它必须包括需要索引和用作组的所有字段。两个 sql_group_column 条目将声明 Assembly 和 Model 可用于过滤结果。并且 search 实用程序将使用 sql_query_info 来查找匹配记录。在查询中,$id 被替换为 searchd 返回的每个主键。
最后一个配置步骤是构建索引。清单 8 显示了数据源 catalog 的索引。
清单 8. 描述 catalog 数据源的一个可能的索引
index catalog
{
source = catalog
path = /var/data/sphinx/catalog
morphology = stem_en
min_word_len = 3
min_prefix_len = 0
min_infix_len = 3
}
第 1 行将指向 sphinx.conf 文件中的指定数据源。第 2 行将定义存储索引数据的位置;按照约定,Sphinx 索引将被存储到 /var/data/sphinx 中。第 3 行将允许索引使用英文词法。并且第 5 行至第 7 行将告诉索引器只索引含有三个字符或更多字符的那些单词,并且为每个这样的字符的子字符串创建中缀索引(为了便于引用,清单 9 显示了 Body Parts 的完整示例 sphinx.conf 文件)。