用 PHP 構(gòu)建自定義搜索引擎_PHP教程

      編輯Tag賺U幣
      教程Tag:暫無Tag,歡迎添加,賺取U幣!

      推薦:PHP連接遠(yuǎn)程MYSQL和MYSQL5.1中文亂碼處理方法
      本文描述了我在開發(fā)我的Blog的過程中所遇到的一些問題以及解決他們的方法。因?yàn)楸揪W(wǎng)站采用的是一個(gè)免費(fèi)的遠(yuǎn)程MySql數(shù)據(jù)庫db4free.net,而且這個(gè)數(shù)據(jù)庫是5.1的版本,所以在開發(fā)過程中出現(xiàn)了許多問

      雖然 Google 及其系列產(chǎn)品幾乎無所不能,但是 Web 形式的強(qiáng)大搜索引擎并不能很好地適用于每個(gè)站點(diǎn)。如果站點(diǎn)內(nèi)容已被高度專業(yè)化或已明確分類,那就需要使用 Sphinx 和 PHP 來創(chuàng)建一個(gè)優(yōu)化的本地搜索系統(tǒng)。

      在 Internet 時(shí)代,人們希望信息能夠像快餐一樣被打包起來:能夠快速無障礙使用,并且分為很小的單位(或者是以字節(jié) 大小為單位?)。實(shí)際上,為了滿足急躁而又渴求信息的用戶的需求,甚至最普通的 Web 站點(diǎn)現(xiàn)在都要求具有快速瀏覽樣式的各種菜單:

      ·RSS 是比薩快遞員,會把新鮮出爐的比薩送上門。

      ·網(wǎng)絡(luò)日志是當(dāng)?shù)氐闹胁宛^,為您獻(xiàn)上喜愛的風(fēng)味菜肴。

      ·論壇是家常便飯(或者可能更恰當(dāng)?shù)卣f,“動物屋” 中搶奪食物的場景)。

      ·而搜索就像在當(dāng)?shù)氐牟蛷d吃自助晚餐一樣:不斷將想吃的食物填滿盤子就行,只要您的食道 —— 還有您的椅子 —— 撐得住。

      幸運(yùn)的是,PHP 開發(fā)人員可以找到各種 RSS、blog 和論壇軟件來創(chuàng)建或者改進(jìn)站點(diǎn)。而且,雖然 Google 和其他搜索站點(diǎn)幾乎無所不能并且執(zhí)行過濾通信,但是搜索引擎并不一定會良好地適應(yīng)各個(gè)站點(diǎn)。

      例如,如果 Web 站點(diǎn)提供成百上千的全新和翻新的保時(shí)捷汽車零件,Google 可能通過諸如 “Carrera parts” 之類的廣義搜索找到您的站點(diǎn),但是對于更具體的 “used 1991 Porsche 911 Targa headlight bezel” 查詢,它可能不會得到精確結(jié)果。

      如果站點(diǎn)內(nèi)容高度專業(yè)化,或者訪問者期望搜索功能與現(xiàn)實(shí)工作流類似,那么最好在 Web 的全局搜索引擎基礎(chǔ)上增加一個(gè)為您的站點(diǎn)量身定做的本地搜索系統(tǒng)(有關(guān)專業(yè)化搜索的更多實(shí)例,請參閱 “A needle in a billion haystacks”)。

      通過本文了解如何向 PHP 站點(diǎn)中添加一個(gè)快速、高效、開源和免費(fèi)的搜索引擎。本文沒有開發(fā)可見的 Web 站點(diǎn)。相反,重點(diǎn)討論交付有效搜索結(jié)果所需的組件:數(shù)據(jù)庫、索引、搜索引擎和 PHP 應(yīng)用程序編程接口 (API)。

      訪問優(yōu)秀的 sphinx

      要為站點(diǎn)提供自定義搜索功能,您必須有數(shù)據(jù)源和搜索該數(shù)據(jù)源的功能。對于 Web 應(yīng)用程序,數(shù)據(jù)源通常是一個(gè)關(guān)系數(shù)據(jù)庫,其中內(nèi)置了一些搜索功能(Equality 是一個(gè)簡單的搜索運(yùn)算符,與 SQL 運(yùn)算符 LIKE 一樣)。但是,一些搜索可能比數(shù)據(jù)庫可以執(zhí)行的搜索更加具體,或者搜索可能過于復(fù)雜,而導(dǎo)致固有的 SQL JOIN 反應(yīng)遲鈍。

      海底撈針

      許多站點(diǎn)提供特定于某一個(gè)行業(yè)、職業(yè)或者娛樂的內(nèi)容,例如醫(yī)藥、法律、音樂和汽車維修。深入研究這些內(nèi)容可能要求使用特殊工具或者培訓(xùn),或者僅需要使用一個(gè)索引來生成相關(guān)的實(shí)用結(jié)果。

      下面是一些需要定制搜索系統(tǒng)的常見搜索場景:

      ·查找 Joe Hockey 所撰寫的關(guān)于斯坦利杯 (Stanley Cup) 的所有文章。

      ·查找 HP LaserJet 3015 All-in-One 打印機(jī)的最新驅(qū)動程序。

      ·查找 Dinosaur Jr. 參與大衛(wèi)深夜脫口秀節(jié)目的電視片段。

      要加速搜索,您可以重新安排表,并由此簡化底層查詢(表和 SQL 查詢優(yōu)化高度依賴于模式和引擎。可通過在線搜索查找有關(guān)數(shù)據(jù)庫性能的各種文章和書籍)。此外,您可以添加一個(gè)專門化的搜索引擎。應(yīng)用哪種形式的搜索引擎還依賴于數(shù)據(jù)的形式(和數(shù)量)和預(yù)算。有許多選擇可用:您可以將一個(gè) Google 工具連接到您的網(wǎng)絡(luò)中,購買 Endeca 或其他大型商業(yè)搜索產(chǎn)品,或者嘗試 Lucene。但是在很多情況下,使用商業(yè)產(chǎn)品都有點(diǎn)小題大做,或者浪費(fèi)運(yùn)營預(yù)算,并且 Lucene 在 2007 年 7 月編寫時(shí)并未提供 PHP API。

      作為一個(gè)備選方案,考慮一下 Sphinx,它是一種開源和免費(fèi)的搜索引擎,可以非常快速地搜索文本。例如,在一個(gè)幾乎有 300,000 行及五個(gè)索引列(每列包含大約 15 個(gè)單詞)的活動數(shù)據(jù)庫中,Sphinx 可以在 1/100 秒內(nèi)得到 “這些單詞中任何一個(gè)單詞” 的搜索結(jié)果(在運(yùn)行 Debian Linux? Sarge 的 2-GHz AMD Opteron 處理器、1 GB RAM 的計(jì)算機(jī)上)。

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

      ·它可以為能夠表示為字符串的所有數(shù)據(jù)建立索引。

      ·它可以以各種方式為相同數(shù)據(jù)建立索引。對于多個(gè)索引,每個(gè)索引都針對特定目的而定制,您可以選擇最適當(dāng)?shù)乃饕齺韮?yōu)化搜索結(jié)果。

      ·它可以把屬性與每條索引數(shù)據(jù)關(guān)聯(lián)起來。然后您可以使用一個(gè)或多個(gè)屬性來進(jìn)一步過濾搜索結(jié)果。

      ·它支持詞法,因此搜索單詞 “cats” 還會找到詞根 “cat”。

      ·您可以在許多計(jì)算機(jī)中分發(fā) Sphinx 索引,從而提供故障恢復(fù)功能。

      ·它可以創(chuàng)建任意長度的單詞前綴索引和可變長度的中綴子字符串的索引。例如,一個(gè)零件號可以是 10 個(gè)字符寬。前綴索引將匹配位于字符串開頭處的所有可能的子字符串。中綴索引將匹配在字符串內(nèi)任意位置的子字符串。

      ·您可以在 MySQL V5 內(nèi)將其作為存儲引擎運(yùn)行,降低使用其他守護(hù)程序的需求(通常被視為另一個(gè)故障點(diǎn))。

      您可以在 Sphinx 源代碼附帶的 README 文件中或通過在線資料找到完整的功能列表。Sphinx Web 站點(diǎn)還列出了已經(jīng)部署了 Sphinx 的若干個(gè)項(xiàng)目。

      Sphinx 是用 C 編寫、用 GNU 編譯器構(gòu)建、支持 64 位支持平臺,并在 Linux、UNIX?、Microsoft? Windows? 和 Mac OS X 上運(yùn)行。構(gòu)建 Sphinx 十分簡單:下載并解壓縮代碼,然后運(yùn)行 ./configure && make && make install 命令。

      默認(rèn)情況下,Sphinx 實(shí)用程序?qū)⒈话惭b到 /usr/local/bin/ 中,并且所有 Sphinx 組件的配置文件都位于 /usr/local/etc/sphinx.conf 中。

      Sphinx 有三個(gè)組件:索引生成器、搜索引擎和命令行 search 實(shí)用程序:

      ·索引生成器被稱為索引器。它將查詢數(shù)據(jù)庫,為結(jié)果的每行中的每列建立索引,并且將每個(gè)索引條目綁定到行的主鍵上。

      ·搜索引擎是名為 searchd 的守護(hù)程序。該守護(hù)程序?qū)⒔邮账阉髟~和其他參數(shù),快速遍歷一個(gè)或多個(gè)索引,并返回結(jié)果。如果找到匹配,searchd 將返回一個(gè)主鍵數(shù)組。對于這些鍵,應(yīng)用程序可以針對相關(guān)數(shù)據(jù)庫運(yùn)行查詢來查找包含匹配的完整記錄。Searchd 將在端口 3312 上通過套接字連接與應(yīng)用程序進(jìn)行通信。

      ·便捷的 search 實(shí)用程序使您可以從命令行構(gòu)造搜索而無需編寫代碼。如果 searchd 返回匹配,則 search 將查詢數(shù)據(jù)庫并顯示匹配集中的行。search 實(shí)用程序?qū)τ谡{(diào)試 Sphinx 配置和執(zhí)行臨時(shí)搜索十分有用。

      此外,Sphinx 的作者 Andrew Aksyonoff 和其他貢獻(xiàn)者為 PHP、Perl、C/C 和其他編程語言提供了 API。

      搜索車身零件

      假定 Body-Parts.com 出售車身零件 —— 擋泥板、鉻、緩沖器等 —— 用于珍貴且值得收藏的汽車。正如在現(xiàn)實(shí)世界中,Body Parts 站點(diǎn)的訪問者很可能按制造商(比如保時(shí)捷或制造同類零件的第三方制造商)、零件號、產(chǎn)地、車型、年份、條件(二手、全新、翻新)以及描述或者這些屬性的某種組合來搜索零件。

      要構(gòu)建 Body Parts 搜索功能,讓我們使用 MySQL V5.0 作為數(shù)據(jù)存儲并使用 Sphinx search 守護(hù)程序來提供快速而精確的文本搜索。MySQL V5.0 是一個(gè)功能強(qiáng)大的數(shù)據(jù)庫,但是它的增強(qiáng)型全文本搜索功能并不特別豐富。實(shí)際上,它僅限于 MyISAM 表 —— 不支持外鍵的一種表格式,因此使用有限。

      清單 1 至清單 4 顯示了與此示例相關(guān)的 Body Parts 模式的部分代碼。您將分別看到 Model(清單 1)、Assembly(清單 2)、Inventory(清單 3)和 Schematic(清單 4)表。

      Model 表

      清單 1 中所示的 Model 表十分簡單:label 列將列舉車型的名稱 (“Corvette”);description 使用客戶友好方式進(jìn)行描述(“兩門跑車;第一年引入”);而 begin_production 和 end_production 分別表示開始生產(chǎn)和結(jié)束生產(chǎn)該車型的年份。由于前述列中的值并不惟一,因此使用一個(gè)獨(dú)立 ID 表示每四個(gè)這樣的元素(label、description、begin_production、end_production),并且是其他表中的外鍵。

      清單 1. 車身零件 Model 表

      以下為引用的內(nèi)容:
      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 表的一些樣例數(shù)據(jù):

      以下為引用的內(nèi)容:
      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 是一個(gè)子系統(tǒng),例如汽車上安裝的傳動裝置或所有玻璃。車主使用部件圖及相關(guān)零件列表來查找備件。清單 2 中所示的 Assembly 表也十分簡單:它將把一個(gè)惟一 ID 與部件標(biāo)簽和描述關(guān)聯(lián)起來。

      清單 2. Assembly 表

      以下為引用的內(nèi)容:
      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;

      繼續(xù)示例,下面是 Assembly 表的一些樣例數(shù)據(jù):

      以下為引用的內(nèi)容:
      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 表是汽車零件的典范列表。零件 —— 例如螺釘或燈泡 —— 可能用于每輛汽車和多個(gè)部件中,但是零件只在 Inventory 表中顯示一次。Inventory 表中的每行包含:

      ·使用了惟一的 32 位整數(shù) serialno 標(biāo)識行。

      ·字母數(shù)字零件號(此零件號惟一并且可以用作主鍵。但是,由于它可以包含字母數(shù)字字符,因此它不適于與 Sphinx 結(jié)合使用,Sphinx 要求索引的每條記錄都有一個(gè)惟一的 32 位整型鍵)。

      ·文本描述。

      ·價(jià)格。

      Inventory 表的規(guī)范如清單 3 中所示:

      清單 3. Inventory 表

      以下為引用的內(nèi)容:

      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 表中的每行都有一個(gè)惟一 ID,一個(gè)引用 Inventory 表行的外鍵,一個(gè)標(biāo)識部件的外鍵,以及用于引用 Model 表中特定型號和版本的另一個(gè)鍵。各行如清單 4 所示:

      清單 4. Schematic 表

      以下為引用的內(nèi)容:
      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;

      為了強(qiáng)化表的意圖,下面是 Schematic 中的一張小型行列表:

      以下為引用的內(nèi)容:
      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);

      搜索表

      定義了這些表后,就可以輕松地響應(yīng)很多搜索:

      ·顯示特定型號的所有版本

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

      ·顯示構(gòu)成特定型號和版本的特殊部件的所有零件

      但是很多搜索代價(jià)較大:

      ·查找所有模型和版本中出現(xiàn)零件號開頭為 “WIN” 的所有零件

      ·查找描述中有 “lacquer” 或 “paint” 的那些零件

      ·查找描述中有 “black leather” 的所有零件

      ·查找描述中有 “paint” 的所有 2002 J 系列零件

      這些搜索中的每個(gè)搜索都要求使用長篇的 JOIN 子句或代價(jià)高昂的 LIKE 子句,尤其是在 Inventory 表和 Schematic 表十分大時(shí)更是如此。而且,復(fù)雜的文本搜索完全超出了 MySQL 的能力。要搜索大量文本數(shù)據(jù),請考慮構(gòu)建和使用 Sphinx 索引。

      集成 Sphinx 軟件

      要應(yīng)用 Sphinx 來解決問題,您必須定義一個(gè)或多個(gè)數(shù)據(jù)源以及一個(gè)或多個(gè)索引。

      source 將標(biāo)識數(shù)據(jù)庫來建立索引,提供驗(yàn)證信息,并且定義查詢用以構(gòu)造每行。數(shù)據(jù)源可以隨意地標(biāo)識一列或多列作為過濾器,Sphinx 將之稱為組。您將使用組來過濾結(jié)果。例如,單詞描述可能得到 900 個(gè)匹配。如果只對特定型號的汽車匹配感興趣,則可以進(jìn)一步使用型號組進(jìn)行過濾。

      index 將要求獲得數(shù)據(jù)源(即一組數(shù)據(jù)行)并定義應(yīng)當(dāng)如何為已從數(shù)據(jù)源中提取出來的數(shù)據(jù)編目。

      您將在 sphinx.conf 文件中定義數(shù)據(jù)源和索引。Body Parts 的數(shù)據(jù)源是 MySQL 數(shù)據(jù)庫。清單 5 顯示了名為 catalog 的數(shù)據(jù)源的部分定義 —— 指定連接的數(shù)據(jù)庫以及如何建立連接(主機(jī)、套接字、用戶和密碼)的代碼片段。

      清單 5. 用于訪問 MySQL 數(shù)據(jù)庫的設(shè)置

      以下為引用的內(nèi)容:

      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

      接下來,創(chuàng)建一個(gè)查詢以生成要被索引的行。通常,將創(chuàng)建 SELECT 子句,可能需要把許多表 JOIN 在一起才能得到行。但這里存在一個(gè)問題:搜索型號和年份必須使用 Assembly 表,但是零件號和零件描述只能在 Inventory 表中找到。為此,Sphinx 必須能夠把搜索結(jié)果與 32 位整型主鍵綁定在一起。

      要獲得右側(cè)表單中的數(shù)據(jù),需要?jiǎng)?chuàng)建一個(gè)視圖 —— MySQL V5 中的新結(jié)構(gòu),它將把來自其他表的列整合到單獨(dú)的合成虛擬表中。使用視圖,各類搜索所需的所有數(shù)據(jù)都在一個(gè)位置,但是活動數(shù)據(jù)實(shí)際上存在于其他表中。清單 6 顯示了定義 Catalog 視圖的 SQL。

      清單 6. Catalog 視圖將把數(shù)據(jù)整合到虛擬表中

      以下為引用的內(nèi)容:
      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;

      如果用前面所示的表和數(shù)據(jù)創(chuàng)建名為 body_parts 的數(shù)據(jù)庫,則 Catalog 視圖應(yīng)當(dāng)類似以下內(nèi)容:

      以下為引用的內(nèi)容:
      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 列用作進(jìn)一步過濾結(jié)果的組。視圖就緒后,構(gòu)造數(shù)據(jù)源查詢就是小事一樁。清單 7 顯示了 catalog 數(shù)據(jù)源定義的其余部分。

      清單 7. 查詢創(chuàng)建待索引的行

      以下為引用的內(nèi)容:

      # 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 必須包括后續(xù)查找需要使用的主鍵,并且它必須包括需要索引和用作組的所有字段。兩個(gè) sql_group_column 條目將聲明 Assembly 和 Model 可用于過濾結(jié)果。并且 search 實(shí)用程序?qū)⑹褂?sql_query_info 來查找匹配記錄。在查詢中,$id 被替換為 searchd 返回的每個(gè)主鍵。

      最后一個(gè)配置步驟是構(gòu)建索引。清單 8 顯示了數(shù)據(jù)源 catalog 的索引。

      清單 8. 描述 catalog 數(shù)據(jù)源的一個(gè)可能的索引

      以下為引用的內(nèi)容:

      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 文件中的指定數(shù)據(jù)源。第 2 行將定義存儲索引數(shù)據(jù)的位置;按照約定,Sphinx 索引將被存儲到 /var/data/sphinx 中。第 3 行將允許索引使用英文詞法。并且第 5 行至第 7 行將告訴索引器只索引含有三個(gè)字符或更多字符的那些單詞,并且為每個(gè)這樣的字符的子字符串創(chuàng)建中綴索引(為了便于引用,清單 9 顯示了 Body Parts 的完整示例 sphinx.conf 文件)。

      清單 9. Body Parts 的示例 sphinx.conf

      以下為引用的內(nèi)容:

      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 守護(hù)程序本身。該部分中的條目不言自明。query.log 尤為有用:它將在運(yùn)行時(shí)顯示每次搜索并顯示結(jié)果,例如搜索的文檔數(shù)和匹配總數(shù)。

      構(gòu)建和測試索引

      您現(xiàn)在已經(jīng)準(zhǔn)備好為 Body Parts 應(yīng)用程序構(gòu)建索引。為此,需要執(zhí)行以下步驟:

      鍵入 $ sudo mkdir -p /var/data/sphinx 創(chuàng)建目錄結(jié)構(gòu) /var/data/sphinx

      假定 MySQL 正在運(yùn)行,使用如下所示的代碼運(yùn)行索引器來創(chuàng)建索引。

      清單 10. 創(chuàng)建索引

      以下為引用的內(nèi)容:

      $ 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 參數(shù)將重構(gòu) sphinx.conf 中列出的所有索引。如果不需要重構(gòu)所有索引,您可以使用其他參數(shù)只對部分索引進(jìn)行重構(gòu)。

      您現(xiàn)在可以使用如下所示的代碼用 search 實(shí)用程序測試索引(不必運(yùn)行 searchd 即可使用 search)。

      清單 11. 用 search 測試索引

      以下為引用的內(nèi)容:

      $ /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 在零件號中找到了兩個(gè)含有 ENG 的結(jié)果。第二條命令 /usr/local/bin/search --config /usr/local/etc/sphinx.conf wind 在兩個(gè)零件描述中找到了子字符串 wind。而第三條命令把結(jié)果限定為 model 為 3 的條目。

      編寫代碼

      最后,您可以編寫 PHP 代碼來調(diào)用 Sphinx 搜索引擎。Sphinx PHP API 非常小并且易于掌握。清單 12 是一個(gè)小型 PHP 應(yīng)用程序,用于調(diào)用 searchd 以得到使用上面所示的最后一條命令得到的相同結(jié)果(“在屬于型號 3 的名稱中找到含有 ‘cylinder’ 的所有零件”)。

      清單 12. 從 PHP 調(diào)用 Sphinx 搜索引擎

      以下為引用的內(nèi)容:

      <?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 創(chuàng)建 log 目錄,啟動 searchd,然后運(yùn)行 PHP 應(yīng)用程序,如下所示:

      清單 13. PHP 應(yīng)用程序

      以下為引用的內(nèi)容:

      $ 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 找到匹配,相關(guān)數(shù)組 $result 將包含名為 results 的元素。瀏覽 print_r() 的輸出以查看返回的其他內(nèi)容。

      注意事項(xiàng):total_found 是在索引中找到的匹配總數(shù),而 found 是返回的結(jié)果數(shù)。這兩者可能不同,因?yàn)槟梢愿拿看畏祷囟嗌賯(gè)匹配結(jié)果以及要返回哪批匹配結(jié)果,哪個(gè)結(jié)果利于對冗長的結(jié)果列表分頁。請查看 API 調(diào)用 SetLimits()。一個(gè)分頁示例是用 $cl->SetLimits( ( $page - 1 ) * SPAN, SPAN ) 調(diào)用搜索引擎返回第一批、第二批、第三批(依此類推)SPAN 匹配結(jié)果,這取決于顯示哪個(gè)頁面。

      結(jié)束語

      Sphinx 還有更多的功能可以利用。我在這里僅僅介紹了最淺顯的一部分,但是您現(xiàn)在有一個(gè)可以工作的現(xiàn)實(shí)示例作為基石來擴(kuò)展您的技能。

      仔細(xì)研讀隨發(fā)行版附帶的樣例 Sphinx 配置文件 /usr/local/etc/sphinx.conf.dist。該文件中的注釋將說明每個(gè) Sphinx 參數(shù)可以實(shí)現(xiàn)的功能;展示如何創(chuàng)建分布式冗余配置;并說明如何繼承基本設(shè)置以避免源代碼及索引中的重復(fù)。Sphinx README 文件還是十分豐富的信息源,包括如何將 Sphinx 直接嵌入 MySQL V5 —— 不需要使用守護(hù)程序。

      分享:PHP實(shí)例:email address 生成圖片程序
      把下面的文件保存為index.php 以下為引用的內(nèi)容: <? /* MailX Managment System 0.8 Beta */ header("Content-type:image/png&

      來源:模板無憂//所屬分類:PHP教程/更新時(shí)間:2008-08-22
      相關(guān)PHP教程