PHP使用 Sphinx 索引内…

来源:互联网 发布:c语言用递归求n的阶乘 编辑:程序博客网 时间:2024/05/16 00:48

集成 Sphinx 软件

http://www.ibm.com/developerworks/cn/opensource/os-php-sphinxsearch/

要应用 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 ASSELECT  Inventory.id,  Inventory.partno,  Inventory.description,  Assembly.id AS assembly,  Model.id AS modelFROM  Assembly, Inventory, Model, SchematicWHERE  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 changedmysql> 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 文件)。

清单 9. Body Parts 的示例 sphinx.conf
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                      # 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}index catalog{    source                  = catalog    path                    = /var/data/sphinx/catalog    morphology              = stem_en    min_word_len            = 3    min_prefix_len          = 0    min_infix_len           = 3}searchd{        port                            = 3312        log                                     = /var/log/searchd/searchd.log        query_log                       = /var/log/searchd/query.log        pid_file                        = /var/log/searchd/searchd.pid}

底部的 searchd 部分将配置searchd 守护程序本身。该部分中的条目不言自明。query.log尤为有用:它将在运行时显示每次搜索并显示结果,例如搜索的文档数和匹配总数。

回页首

构建和测试索引

您现在已经准备好为 Body Parts 应用程序构建索引。为此,需要执行以下步骤:

  1. 键入 $ sudomkdir -p /var/data/sphinx 创建目录结构/var/data/sphinx
  2. 假定 MySQL 正在运行,使用如下所示的代码运行索引器来创建索引。
    清单 10. 创建索引
    $ sudo /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf --allSphinx 0.9.7Copyright (c) 2001-2007, Andrew Aksyonoffusing config file '/usr/local/etc/sphinx.conf'...indexing index 'catalog'...collected 8 docs, 0.0 MBsorted 0.0 Mhits, 82.8% donetotal 8 docs, 149 bytestotal 0.010 sec, 14900.00 bytes/sec, 800.00 docs/sec
    注:-all 参数将重构sphinx.conf 中列出的所有索引。如果不需要重构所有索引,您可以使用其他参数只对部分索引进行重构。
  3. 您现在可以使用如下所示的代码用 search 实用程序测试索引(不必运行 searchd 即可使用 search)。
    清单 11. 用 search 测试索引
    $ /usr/local/bin/search --config /usr/local/etc/sphinx.conf ENGSphinx 0.9.7Copyright (c) 2001-2007, Andrew Aksyonoffindex 'catalog': query 'ENG ': returned 2 matches of 2 total in 0.000 secdisplaying matches:1. document=8, weight=1, assembly=5, model=7        id=8        partno=ENG088        description=Cylinder head        price=552. document=9, weight=1, assembly=5, model=3        id=9        partno=ENG976        description=Large cylinder head        price=65words:1. 'eng': 2 documents, 2 hits$ /usr/local/bin/search --config /usr/local/etc/sphinx.conf wind Sphinx 0.9.7Copyright (c) 2001-2007, Andrew Aksyonoffindex 'catalog': query 'wind ': returned 2 matches of 2 total in 0.000 secdisplaying matches:1. document=1, weight=1, assembly=3, model=1        id=1        partno=WIN408        description=Portal window        price=4232. document=5, weight=1, assembly=3, model=1        id=5        partno=WIN958        description=Windshield, front        price=500words:1. 'wind': 2 documents, 2 hits$ /usr/local/bin/search \--config /usr/local/etc/sphinx.conf --filter  model 3 ENGSphinx 0.9.7Copyright (c) 2001-2007, Andrew Aksyonoffindex 'catalog': query 'ENG ': returned 1 matches of 1 total in 0.000 secdisplaying matches:1. document=9, weight=1, assembly=5, model=3        id=9        partno=ENG976        description=Large cylinder head        price=65words:1. 'eng': 2 documents, 2 hits

第一条命令 /usr/local/bin/search--config /usr/local/etc/sphinx.conf ENG 在零件号中找到了两个含有 ENG 的结果。第二条命令/usr/local/bin/search--config /usr/local/etc/sphinx.conf wind 在两个零件描述中找到了子字符串 wind。而第三条命令把结果限定为 model  3 的条目。

回页首

编写代码

最后,您可以编写 PHP 代码来调用 Sphinx 搜索引擎。Sphinx PHP API 非常小并且易于掌握。清单 12 是一个小型PHP 应用程序,用于调用 searchd 以得到使用上面所示的最后一条命令得到的相同结果(“在属于型号 3 的名称中找到含有‘cylinder’ 的所有零件”)。

清单 12. 从 PHP 调用 Sphinx 搜索引擎

要测试代码,需要为 Sphinx 创建 log 目录,启动 searchd,然后运行 PHP 应用程序,如下所示:

清单 13. PHP 应用程序
$ sudo mkdir -p /var/log/searchd$ sudo /usr/local/bin/searchd --config /usr/local/etc/sphinx.conf$ php search.php 9Array(    [fields] => Array        (            [0] => partno            [1] => description        )    [attrs] => Array        (            [assembly] => 1            [model] => 1        )    [matches] => Array        (            [9] => Array                (                    [weight] => 1                    [attrs] => Array                        (                            [assembly] => 5                            [model] => 3                        )                )        )    [total] => 1    [total_found] => 1    [time] => 0.000    [words] => Array        (            [cylind] => Array                (                    [docs] => 2                    [hits] => 2                )        ))

输出为 9:匹配的单行的正确主键。如果Sphinx 找到匹配,相关数组 $result 将包含名为 results 的元素。浏览 print_r() 的输出以查看返回的其他内容。

注意事项:total_found 是在索引中找到的匹配总数,而 found 是返回的结果数。这两者可能不同,因为您可以更改每次返回多少个匹配结果以及要返回哪批匹配结果,哪个结果利于对冗长的结果列表分页。请查看API 调用 SetLimits()。一个分页示例是用 $cl->SetLimits(( $page - 1 ) * SPAN, SPAN ) 调用搜索引擎返回第一批、第二批、第三批(依此类推)SPAN 匹配结果,这取决于显示哪个页面。

回页首

结束语

Sphinx还有更多的功能可以利用。我在这里仅仅介绍了最浅显的一部分,但是您现在有一个可以工作的现实示例作为基石来扩展您的技能。

仔细研读随发行版附带的样例 Sphinx 配置文件/usr/local/etc/sphinx.conf.dist。该文件中的注释将说明每个 Sphinx参数可以实现的功能;展示如何创建分布式冗余配置;并说明如何继承基本设置以避免源代码及索引中的重复。Sphinx README文件还是十分丰富的信息源,包括如何将 Sphinx 直接嵌入 MySQL V5 —— 不需要使用守护程序。

0 0