首页 > 语言 > 关键词 > php最新资讯 > 正文

用 PHP 构建自定义搜索引擎

2007-11-19 09:57 · 稿源:网页教学网

虽然 Google 及其系列产品几乎无所不能,但是 Web 形式的强大搜索引擎并不能很好地适用于每个站点。如果站点内容已被高度专业化或已明确分类,那就需要使用 Sphinx 和 PHP 来创建一个优化的本地搜索系统。

在 Internet 时代,人们希望信息能够像快餐一样被打包起来:能够快速无障碍使用,并且分为很小的单位(或者是以字节 大小为单位?)。实际上,为了满足急躁而又渴求信息的用户的需求,甚至最普通的 Web 站点现在都要求具有快速浏览样式的各种菜单:

·RSS 是比萨快递员,会把新鲜出炉的比萨送上门。

·网络日志是当地的中餐馆,为您献上喜爱的风味菜肴。

·论坛是家常便饭(或者可能更恰当地说,“动物屋” 中抢夺食物的场景)。

·而搜索就像在当地的餐厅吃自助晚餐一样:不断将想吃的食物填满盘子就行,只要您的食道 —— 还有您的椅子 —— 撑得住。

幸运的是,PHP 开发人员可以找到各种 RSS、blog 和论坛软件来创建或者改进站点。而且,虽然 Google 和其他搜索站点几乎无所不能并且执行过滤通信,但是搜索引擎并不一定会良好地适应各个站点。

例如,如果 Web 站点提供成百上千的全新和翻新的保时捷汽车零件,Google 可能通过诸如 “Carrera parts” 之类的广义搜索找到您的站点,但是对于更具体的 “used 1991 Porsche 911 Targa headlight bezel” 查询,它可能不会得到精确结果。

如果站点内容高度专业化,或者访问者期望搜索功能与现实工作流类似,那么最好在 Web 的全局搜索引擎基础上增加一个为您的站点量身定做的本地搜索系统(有关专业化搜索的更多实例,请参阅 “A needle in a billion haystacks”)。

通过本文了解如何向 PHP 站点中添加一个快速、高效、开源和免费的搜索引擎。本文没有开发可见的 Web 站点。相反,重点讨论交付有效搜索结果所需的组件:数据库、索引、搜索引擎和 PHP 应用程序编程接口 (API)。

访问优秀的 sphinx

要为站点提供自定义搜索功能,您必须有数据源和搜索该数据源的功能。对于 Web 应用程序,数据源通常是一个关系数据库,其中内置了一些搜索功能(Equality 是一个简单的搜索运算符,与 SQL 运算符 LIKE 一样)。但是,一些搜索可能比数据库可以执行的搜索更加具体,或者搜索可能过于复杂,而导致固有的 SQL JOIN 反应迟钝。

海底捞针

许多站点提供特定于某一个行业、职业或者娱乐的内容,例如医药、法律、音乐和汽车维修。深入研究这些内容可能要求使用特殊工具或者培训,或者仅需要使用一个索引来生成相关的实用结果。

下面是一些需要定制搜索系统的常见搜索场景:

·查找 Joe Hockey 所撰写的关于斯坦利杯 (Stanley Cup) 的所有文章。

·查找 HP LaserJet 3015 All-in-One 打印机的最新驱动程序。

·查找 Dinosaur Jr. 参与大卫深夜脱口秀节目的电视片段。

要加速搜索,您可以重新安排表,并由此简化底层查询(表和 SQL 查询优化高度依赖于模式和引擎。可通过在线搜索查找有关数据库性能的各种文章和书籍)。此外,您可以添加一个专门化的搜索引擎。应用哪种形式的搜索引擎还依赖于数据的形式(和数量)和预算。有许多选择可用:您可以将一个 Google 工具连接到您的网络中,购买 Endeca 或其他大型商业搜索产品,或者尝试 Lucene。但是在很多情况下,使用商业产品都有点小题大做,或者浪费运营预算,并且 Lucene 在 2007 年 7 月编写时并未提供 PHP API。

作为一个备选方案,考虑一下 Sphinx,它是一种开源和免费的搜索引擎,可以非常快速地搜索文本。例如,在一个几乎有 300,000 行及五个索引列(每列包含大约 15 个单词)的活动数据库中,Sphinx 可以在 1/100 秒内得到 “这些单词中任何一个单词” 的搜索结果(在运行 Debian Linux? Sarge 的 2-GHz AMD Opteron 处理器、1 GB RAM 的计算机上)。

Sphinx 提供了大量功能,包括:

·它可以为能够表示为字符串的所有数据建立索引。

·它可以以各种方式为相同数据建立索引。对于多个索引,每个索引都针对特定目的而定制,您可以选择最适当的索引来优化搜索结果。

·它可以把属性与每条索引数据关联起来。然后您可以使用一个或多个属性来进一步过滤搜索结果。

·它支持词法,因此搜索单词 “cats” 还会找到词根 “cat”。

·您可以在许多计算机中分发 Sphinx 索引,从而提供故障恢复功能。

·它可以创建任意长度的单词前缀索引和可变长度的中缀子字符串的索引。例如,一个零件号可以是 10 个字符宽。前缀索引将匹配位于字符串开头处的所有可能的子字符串。中缀索引将匹配在字符串内任意位置的子字符串。

·您可以在 MySQL V5 内将其作为存储引擎运行,降低使用其他守护程序的需求(通常被视为另一个故障点)。

您可以在 Sphinx 源代码附带的 README 文件中或通过在线资料找到完整的功能列表。Sphinx Web 站点还列出了已经部署了 Sphinx 的若干个项目。

Sphinx 是用 C++ 编写、用 GNU 编译器构建、支持 64 位支持平台,并在 Linux、UNIX?、Microsoft? Windows? 和 Mac OS X 上运行。构建 Sphinx 十分简单:下载并解压缩代码,然后运行 ./configure && make && make install 命令。

默认情况下,Sphinx 实用程序将被安装到 /usr/local/bin/ 中,并且所有 Sphinx 组件的配置文件都位于 /usr/local/etc/sphinx.conf 中。

Sphinx 有三个组件:索引生成器、搜索引擎和命令行 search 实用程序:

·索引生成器被称为索引器。它将查询数据库,为结果的每行中的每列建立索引,并且将每个索引条目绑定到行的主键上。

·搜索引擎是名为 searchd 的守护程序。该守护程序将接收搜索词和其他参数,快速遍历一个或多个索引,并返回结果。如果找到匹配,searchd 将返回一个主键数组。对于这些键,应用程序可以针对相关数据库运行查询来查找包含匹配的完整记录。Searchd 将在端口 3312 上通过套接字连接与应用程序进行通信。

·便捷的 search 实用程序使您可以从命令行构造搜索而无需编写代码。如果 searchd 返回匹配,则 search 将查询数据库并显示匹配集中的行。search 实用程序对于调试 Sphinx 配置和执行临时搜索十分有用。

此外,Sphinx 的作者 Andrew Aksyonoff 和其他贡献者为 PHP、Perl、C/C++ 和其他编程语言提供了 API。

搜索车身零件

假定 Body-Parts.com 出售车身零件 —— 挡泥板、铬、缓冲器等 —— 用于珍贵且值得收藏的汽车。正如在现实世界中,Body Parts 站点的访问者很可能按制造商(比如保时捷或制造同类零件的第三方制造商)、零件号、产地、车型、年份、条件(二手、全新、翻新)以及描述或者这些属性的某种组合来搜索零件。

要构建 Body Parts 搜索功能,让我们使用 MySQL V5.0 作为数据存储并使用 Sphinx search 守护程序来提供快速而精确的文本搜索。MySQL V5.0 是一个功能强大的数据库,但是它的增强型全文本搜索功能并不特别丰富。实际上,它仅限于 MyISAM 表 —— 不支持外键的一种表格式,因此使用有限。

清单 1 至清单 4 显示了与此示例相关的 Body Parts 模式的部分代码。您将分别看到 Model(清单 1)、Assembly(清单 2)、Inventory(清单 3)和 Schematic(清单 4)表。

Model 表

清单 1 中所示的 Model 表十分简单:label 列将列举车型的名称 (“Corvette”);description 使用客户友好方式进行描述(“两门跑车;第一年引入”);而 begin_production 和 end_production 分别表示开始生产和结束生产该车型的年份。由于前述列中的值并不惟一,因此使用一个独立 ID 表示每四个这样的元素(label、description、begin_production、end_production),并且是其他表中的外键。

清单 1. 车身零件 Model 表

以下为引用的内容:
CREATE TABLE Model (
id int(10) unsigned NOT NULL auto_increment,
label varchar(7) NOT NULL,
description varchar(256) NOT NULL,
begin_production int(4) NOT NULL,
end_production int(4) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

下面是 Model 表的一些样例数据:

以下为引用的内容:
INSERT INTO Model
(`id`, `label`, `description`, `begin_production`, `end_production`)
VALUES
(1,'X Sedan','Four-door performance sedan',1998,1999),
(3,'X Sedan','Four door performance sedan, 1st model year',1995,1997),
(4,'J Convertible','Two-door roadster, metal retracting roof',2002,2005),
(5,'J Convertible','Two-door roadster',2000,2001),
(7,'W Wagon','Four-door, all-wheel drive sport station wagon',2007,0);

Assembly 表

assembly 是一个子系统,例如汽车上安装的传动装置或所有玻璃。车主使用部件图及相关零件列表来查找备件。清单 2 中所示的 Assembly 表也十分简单:它将把一个惟一 ID 与部件标签和描述关联起来。

清单 2. Assembly 表

以下为引用的内容:
CREATE TABLE Assembly (
id int(10) unsigned NOT NULL auto_increment,
label varchar(7) NOT NULL,
description varchar(128) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

继续示例,下面是 Assembly 表的一些样例数据:

以下为引用的内容:
INSERT INTO Assembly
(`id`, `label`, `description`)
VALUES
(1,'5-00','Seats'),
(2,'4-00','Electrical'),
(3,'3-00','Glasses'),
(4,'2-00','Frame'),
(5,'1-00','Engine'),
(7,'101-00','Accessories');

Inventory 表

Inventory 表是汽车零件的典范列表。零件 —— 例如螺钉或灯泡 —— 可能用于每辆汽车和多个部件中,但是零件只在 Inventory 表中显示一次。Inventory 表中的每行包含:

·使用了惟一的 32 位整数 serialno 标识行。

·字母数字零件号(此零件号惟一并且可以用作主键。但是,由于它可以包含字母数字字符,因此它不适于与 Sphinx 结合使用,Sphinx 要求索引的每条记录都有一个惟一的 32 位整型键)。

·文本描述。

·价格。

Inventory 表的规范如清单 3 中所示:

清单 3. Inventory 表

以下为引用的内容:

CREATE TABLE Inventory (
id int(10) unsigned NOT NULL auto_increment,
partno varchar(32) NOT NULL,
description varchar(256) NOT NULL,
price float unsigned NOT NULL default '0',
PRIMARY KEY (id),
UNIQUE KEY partno USING BTREE (partno)
) ENGINE=InnoDB;

零件的(部分)列表可能如下面所示:

INSERT INTO `Inventory`
(`id`, `partno`, `description`, `price`)
VALUES
(1,'WIN408','Portal window',423),
(2,'ACC711','Jack kit',110),
(3,'ACC43','Rear-view mirror',55),
(4,'ACC5409','Cigarette lighter',20),
(5,'WIN958','Windshield, front',500),
(6,'765432','Bolt',0.1),
(7,'ENG001','Entire engine',10000),
(8,'ENG088','Cylinder head',55),
(9,'ENG976','Large cylinder head',65);

Schematic 表

Schematic 表将把零件与部件和车型版本绑定在一起。因此,将使用 Schematic 表来查找组装 1979 J Class 敞篷车引擎的所有零件。Schematic 表中的每行都有一个惟一 ID,一个引用 Inventory 表行的外键,一个标识部件的外键,以及用于引用 Model 表中特定型号和版本的另一个键。各行如清单 4 所示:

清单 4. Schematic 表

以下为引用的内容:
CREATE TABLE Schematic (
id int(10) unsigned NOT NULL auto_increment,
partno_id int(10) unsigned NOT NULL,
assembly_id int(10) unsigned NOT NULL,
model_id int(10) unsigned NOT NULL,
PRIMARY KEY (id),
KEY partno_index USING BTREE (partno_id),
KEY assembly_index USING BTREE (assembly_id),
KEY model_index USING BTREE (model_id),
FOREIGN KEY (partno_id) REFERENCES Inventory(id),
FOREIGN KEY (assembly_id) REFERENCES Assembly(id),
FOREIGN KEY (model_id) REFERENCES Model(id)
) ENGINE=InnoDB;

为了强化表的意图,下面是 Schematic 中的一张小型行列表:

以下为引用的内容:
INSERT INTO `Schematic`
(`id`, `partno_id`, `assembly_id`, `model_id`)
VALUES
(1,6,5,1),
(2,8,5,1),
(3,1,3,1),
(4,5,3,1),
(5,8,5,7),
(6,6,5,7),
(7,4,7,3),
(8,9,5,3);

搜索表

定义了这些表后,就可以轻松地响应很多搜索:

·显示特定型号的所有版本

·列出装配特殊型号和版本所需的所有部件

·显示构成特定型号和版本的特殊部件的所有零件

但是很多搜索代价较大:

·查找所有模型和版本中出现零件号开头为 “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 文件)。

清单 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 应用程序构建索引。为此,需要执行以下步骤:

键入 $ sudo mkdir -p /var/data/sphinx 创建目录结构 /var/data/sphinx

假定 MySQL 正在运行,使用如下所示的代码运行索引器来创建索引。

清单 10. 创建索引

以下为引用的内容:

$ sudo /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf --all
Sphinx 0.9.7
Copyright (c) 2001-2007, Andrew Aksyonoff

using config file '/usr/local/etc/sphinx.conf'...
indexing index 'catalog'...
collected 8 docs, 0.0 MB
sorted 0.0 Mhits, 82.8% done
total 8 docs, 149 bytes
total 0.010 sec, 14900.00 bytes/sec, 800.00 docs/sec

注:-all 参数将重构 sphinx.conf 中列出的所有索引。如果不需要重构所有索引,您可以使用其他参数只对部分索引进行重构。

您现在可以使用如下所示的代码用 search 实用程序测试索引(不必运行 searchd 即可使用 search)。

清单 11. 用 search 测试索引

以下为引用的内容:

$ /usr/local/bin/search --config /usr/local/etc/sphinx.conf ENG
Sphinx 0.9.7
Copyright (c) 2001-2007, Andrew Aksyonoff

index 'catalog': query 'ENG ': returned 2 matches of 2 total in 0.000 sec

displaying matches:
1. document=8, weight=1, assembly=5, model=7
id=8
partno=ENG088
description=Cylinder head
price=55
2. document=9, weight=1, assembly=5, model=3
id=9
partno=ENG976
description=Large cylinder head
price=65

words:
1. 'eng': 2 documents, 2 hits

$ /usr/local/bin/search --config /usr/local/etc/sphinx.conf wind
Sphinx 0.9.7
Copyright (c) 2001-2007, Andrew Aksyonoff

index 'catalog': query 'wind ': returned 2 matches of 2 total in 0.000 sec

displaying matches:
1. document=1, weight=1, assembly=3, model=1
id=1
partno=WIN408
description=Portal window
price=423
2. document=5, weight=1, assembly=3, model=1
id=5
partno=WIN958
description=Windshield, front
price=500

words:
1. 'wind': 2 documents, 2 hits

$ /usr/local/bin/search \
--config /usr/local/etc/sphinx.conf --filter model 3 ENG
Sphinx 0.9.7
Copyright (c) 2001-2007, Andrew Aksyonoff

index 'catalog': query 'ENG ': returned 1 matches of 1 total in 0.000 sec

displaying matches:
1. document=9, weight=1, assembly=5, model=3
id=9
partno=ENG976
description=Large cylinder head
price=65

words:
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 搜索引擎

以下为引用的内容:

<?php
include('sphinx-0.9.7/api/sphinxapi.php');

$cl = new SphinxClient();
$cl->SetServer( "localhost", 3312 );
$cl->SetMatchMode( SPH_MATCH_ANY );
$cl->SetFilter( 'model', array( 3 ) );

$result = $cl->Query( 'cylinder', 'catalog' );

if ( $result === false ) {
 echo "Query failed: " . $cl->GetLastError() . ".\n";
}
else {
 if ( $cl->GetLastWarning() ) {
  echo "WARNING: " . $cl->GetLastWarning() . "";
 }

 if ( ! empty($result["matches"]) ) {
  foreach ( $result["matches"] as $doc => $docinfo ) {
   echo "$doc\n";
  }

  print_r( $result );
 }
}

exit;
?>

要测试代码,需要为 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
9
Array (
[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 —— 不需要使用守护程序。

  • 相关推荐
  • 大家在看
  • Google 搜索引擎导流作用越来越弱

    Google 联合创始人 Larry Page 和 Sergey Brin 在 2004 年公司上市时说,他们的搜索结果展示是最好的,广告很少,很有用,也不突出。Page 还表示,他们希望用户尽可能快的离开 Google 前往正确的地方。2019 年,美国众议院反垄断委员会主席 David Cicilline 询问这一声明是否还有效。

  • 支付宝被曝狂招搜索人才 官方回应:不做搜索引擎

    7月29日消息,针对近日狂招搜索人才的传闻,支付宝强调:不做搜索引擎,只做服务搜索。支付宝方面向《科创板日报》回应称,“我们的确在招人,春节左右就开始了,今年还会再招200人。但支

  • 请回答,搜索引擎!在自我提问中找到的SEM优化技巧

    SEMer一直在做优化,加词,改创意,调整排名,其实更需要停下来想一想。包括做信息流推广也是一样,抓取精准用户群体,哪些才是我们精准用户呢?我们很少去探究搜索词后面,网民在想啥?他为啥这样去搜索?

  • 互联网图片版权诉讼调研报告:31%用户直接通过搜索引擎获得相关图

    近日,北京互联网法院近日发布关于涉网图片类著作权案件的调研报告。报告指出,个别图片公司或者律师甚至专门从事图片维权诉讼,利用专业软件检索到侵权行为后再向图片权利人寻求授权,以提起诉讼的方式获取不正当商业利益。

  • 快手磁力引擎全面开放Marketing API 构建智能营销新生态

    随着移动互联网进入存量时代,红利即将见顶,广告主投放广告的策略也逐步调整为“在存量用户中寻找增量”。在不断扩大广告投放量的基础上,还需要更精准、更高效的投放,获取更高的ROI转化。与此同时,多平台管理、素材量多、账户多、人力成本高、人效低等诸多挑战也在陆续涌现,这让广告主、代理商“疲于应对”。近期,全新升级的快手磁力引擎Marketing API全面对外开放,具备一定技术能力的广告主、代理商和第三方等均可以接入。

  • 百度搜索资源平台:普通收录和死链提交工具不再支持索引型sitemap文件

    7月8日下午,百度搜索资源平台发布《sitemap提交方式优化公告》称,为了提升sitemap文件的处理效率,即日起搜索资源平台的普通收录和死链提交工具均不再支持索引型sitemap文件(即xml文档嵌套xml文档)。

  • 多科室联动,构建新生儿健康的安全屏障

    7 月 17 日,深圳远东妇产医院龙岗妇产医院为新手爸妈精心准备了一场“迎接新生,守护健康”主题的直播。此次直播嘉宾为远东妇产医院新生儿科学科带头人、新生儿科主任刘晓红,远东龙岗妇产医院大儿科主任、新生儿科主任邓鲲,妇产科主任刘庆平,儿保科主任陈秀花,新生儿科护士长扶希。从妇产、新生儿、儿科全链条为新手爸妈们献计献策,答疑解惑。直播在线观看的新手爸妈达到 20 万+,直播累计观看达255. 4 万人次。科室联动,协

  • 腾讯孙忠怀:内容为本 构建具有长远价值的综合视频平台

    腾讯视频2020年度发布在上海举行。腾讯公司副总裁、企鹅影视CEO孙忠怀出席并发表主题演讲,重点分享了腾讯视频在构建综合型视频平台过程中,在内容创作、合作伙伴标准和生态建设等方面的思考。直面挑战,理性平稳发展目前,腾讯视频整体发展平稳,成绩斐然。孙忠怀表示,上半年,腾讯视频的月活跃人数保持稳定,在2月还创下了2018年以来的新高。用户使用时长依然坚挺,会员数量稳中有增,头部垂类爆款频出

  • OKEx徐坤:构建核心壁垒,拓展全球市场

    7月8日,OKEx首席战略官徐坤做客由谜渡主办的《刀锋对话》栏目,直播环节,徐坤就OKChain技术特点、OKEx应对行业公关战等话题。以下是访谈实录:问题1:有媒体称OKEx是行业最大的黑公关,对此您如何回应?OKEx每年在公关上的预算是多少?都在哪些平台上做过付费广告宣发?您如何看待行业里的公关战,OKEx的原则是什么?OKEx徐坤:市场上各种空穴来风的臆测很多,我们也没有精力一一去查证、澄清,毕竟交易所的主业是为用户提供交易

  • 出海企业“顺风车”来了 木瓜移动构建优质出海业务

    近几年来,随着中国国内市场红利被瓜分无几,海外市场成为了新的流量入口。突然袭卷全球的疫情,使得大部分国内企业出海遭遇瓶颈。木瓜移动作为国内企业出海营销的好帮手,在企业出海方面发挥了不小的作用。大家都知道出海绝非易事,由于很多国内公司对于海外市场并不了解,也缺乏在海外运营的经验。如何快速进入海外市场,整合当地资源,针对目标客户精准营销已然成为了国内企业急需解决的问题。木瓜移动作为国内企业出海营销的好

  • 木瓜移动拟申请创业板 持续构建出海领域蓝图

    今年的大新闻莫过于创业板改革并实行注册制,在创业板上实施注册制,有利于促进中小市值股票更加活跃,而券商、创投公司等将明显受益于创业板注册制制度红利。在当前疫情对经济负面影响较大的背景下,推动创业板注册制改革,有利于推动更多优质的创新型企业登陆资本市场,进一步提升资本市场服务实体经济的能力。作为一家优质的综合类海外营销公司,木瓜移动就拟申请创业板。木瓜移动拟申请创业板 帮助出海企业寻找到目标用户木瓜?

  • 蓝光集团以更懂生活也更懂居住的品牌理念构建自身全国化的战略

    任何的企业都需要建立自己的品牌知名度,提升品牌知名度是企业稳定发展的助力。在此方面,蓝光集团一直以来都坚持着定制化以及生长化的发展理念,打造了系列具备中国温度的产品,为人们带来了全新的舒适居住体验。在蓝光集团看来,想要做具备中国温度的产品便要先做到懂用户所需。只有与用户进行心与心的沟通才能了解到用户真正所需要的是什么,并在这基础上对自身发展进行优化改良创造出更优质的更符合用户要求的产品进而赋予产品

  • 火币宣布成立DeFi实验室,联合全球社区构建DeFi生态

    8 月 3 日,全球知名的数字经济领军企业,火币集团宣布成立火币DeFi实验室。 火币DeFi实验室专注于DeFi(去中心化金融)的研究、投资、孵化、以及生态的建设。计划在未来通过与全球加密领域和DeFi社区合作,构建更好的金融系统。 火币集团创始人兼CEO李林表示:“作为全球知名的数字经济领军企业,我们的使命是让财富更自由,让全球至少一亿家庭拥有数字资产,无论是DeFi还是CeFi。加入全球DeFi生态是一件激动人心的事,同时,也很?

  • 国内首个新基建安全大赛即将启动 攻防视角构建安全体系

    新一轮智能科技创新浪潮正在掀起,从中央密集部署,到行业市场追捧,新基建势必成为 2020 年中国经济的一大“热词”。在这样的背景下, 8 月 3 日,国内首个关注新基建的安全赛事——GeekPwn(极棒)新基建安全大赛启动会将在北京中国大饭店举办,届时将重磅发布详细的新基建安全赛制,面向全产业链招募安全技术精英,从攻防视角探索新基建安全。据悉,本次大赛由中国产业互联网发展联盟指导,腾讯安全与安信天行、任子行、深信服、?

  • 头条、抖音后,谁是字节跳动的新引擎?

    TikTok海外遇阻,全球化失利。作为字节跳动流量和营收支柱,头条和抖音已经或即将碰到天花板。字节跳动疯狂布局游戏、在线教育、电商三大赛道,这里能长出新增长引擎吗?

  • BATH领跑新基建之际,欧科云链构建区块链产业的“数字底座”

    近日,人民网研究院发布新基建研究报告《BATH布局新基建,开启智能经济新时代》,立足当下科技产业整体发展趋势,重点分析了国内领军科技企业的新基建布局,以及参与新基建的核心能力要素。报告指出,以 BATH 为代表的互联网企业争相投入布局新基建,不仅将为新基建带来充沛的资金,在技术、人才等领域也更具有优势。以5G、人工智能为代表的新型基础设施建设,不仅能在中短期内创造大量投资机会、提升发展动能,而且能加速智能经济

  • 加速数字化转型,HPE担纲“新基建”

    在今年的两会上,“新型基础设施”被首次写入了政府工作报告,提出通过发展新一代信息网络、拓展5G应用、建设数据中心等,激发新消费需求、助力产业升级。“新基建”兼具稳增长、调结构、促创新等重大作用,特别是加速数字基础设施建设对于数字化转型和发展数字经济来说具有重大意义。由于数字新基建需要承担稳增长、调结构、促创新等任务,因此混合云就成为了必不可少的基础设施。所谓混合云,就是结合了公有云、私有云和传统IT等形态的

  • 深度对话:巨量引擎不想只卖广告

    “我们想深入到生意的链条中去。其中,会有无数新可能。”巨量引擎营销副总裁陈都烨这样说。今天,今日头条、抖音、西瓜视频等大热的平台,其广告业务都集中于巨量引擎之上。媒体的报道显示,巨量引擎在 2019 年拿下了超过 1000 亿人民币的广告收入,站在中国广告市场的前列。

  • 巨量引擎《动见》:数说直播营销

    商务部数据显示,今年一季度我国电商直播超过400万场,电商直播平台、短视频直播平台的直播场次呈爆炸式增长态势。虽然电商直播并不能代表直播营销的全貌,但它的繁荣足以证明直播商业的重心。6月30日,巨量引擎提供高层次营销洞察与深度研究成果的官方智库平台《动见》正式上线,以“营销的后直播时代”为主题,带来更多关于直播营销的思考。消费者在直播间里看什么根据《2020抖音直播数据图谱》显示,目前在直播间里,80后人均观

  • 搜索竞赛进入2.0,支付宝用“服务搜索”先抢一城

    前天,支付宝宣布首页搜索“品牌直达”能力全新升级,具体体现在“优先展示”、“灵活配置”、“审核提速” 3 大举措。

  • 参与评论
文明上网理性发言,请遵守新闻评论服务协议
  • 热门标签

热文