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

轉(zhuǎn)自:http://www.ibm.com/developerworks/cn/opensource/os-php-sphinxsearch/index.html

搜索車(chē)身零件

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

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

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

Model 表

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

清單 1. 車(chē)身零件 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 表的一些樣例數(shù)據(jù):

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)彤蔽,例如汽車(chē)上安裝的傳動(dòng)裝置或所有玻璃摧莽。車(chē)主使用部件圖及相關(guān)零件列表來(lái)查找備件。清單 2 中所示的 Assembly 表也十分簡(jiǎn)單:它將把一個(gè)惟一 ID 與部件標(biāo)簽和描述關(guān)聯(lián)起來(lái)顿痪。

清單 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;

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

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 表是汽車(chē)零件的典范列表。零件 —— 例如螺釘或燈泡 —— 可能用于每輛汽車(chē)和多個(gè)部件中蚁袭,但是零件只在 Inventory 表中顯示一次征懈。Inventory 表中的每行包含:

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

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

文本描述。

價(jià)格蹬挺。

Inventory 表的規(guī)范如清單 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 表將把零件與部件和車(chē)型版本綁定在一起维贺。因此,將使用 Schematic 表來(lái)查找組裝 1979 J Class 敞篷車(chē)引擎的所有零件汗侵。Schematic 表中的每行都有一個(gè)惟一 ID幸缕,一個(gè)引用 Inventory 表行的外鍵群发,一個(gè)標(biāo)識(shí)部件的外鍵晰韵,以及用于引用 Model 表中特定型號(hào)和版本的另一個(gè)鍵。各行如清單 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;

為了強(qiáng)化表的意圖熟妓,下面是 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);

搜索表

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

顯示特定型號(hào)的所有版本

列出裝配特殊型號(hào)和版本所需的所有部件

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

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

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

查找描述中有 “l(fā)acquer” 或 “paint” 的那些零件

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

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

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

回頁(yè)首

集成 Sphinx 軟件

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

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

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

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

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

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

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

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

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

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ù)庫(kù),則 Catalog 視圖應(yīng)當(dāng)類似以下內(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)一步過(guò)濾結(jié)果的組。視圖就緒后撇叁,構(gòu)造數(shù)據(jù)源查詢就是小事一樁供鸠。清單 7 顯示了 catalog 數(shù)據(jù)源定義的其余部分。

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

# 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 可用于過(guò)濾結(jié)果。并且 search 實(shí)用程序?qū)⑹褂?sql_query_info 來(lái)查找匹配記錄正林。在查詢中泡一,$id 被替換為 searchd 返回的每個(gè)主鍵。

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

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

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 行將定義存儲(chǔ)索引數(shù)據(jù)的位置杈绸;按照約定帖蔓,Sphinx 索引將被存儲(chǔ)到 /var/data/sphinx 中。第 3 行將允許索引使用英文詞法瞳脓。并且第 5 行至第 7 行將告訴索引器只索引含有三個(gè)字符或更多字符的那些單詞塑娇,并且為每個(gè)這樣的字符的子字符串創(chuàng)建中綴索引(為了便于引用,清單 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 守護(hù)程序本身埋酬。該部分中的條目不言自明。query.log 尤為有用:它將在運(yùn)行時(shí)顯示每次搜索并顯示結(jié)果烧栋,例如搜索的文檔數(shù)和匹配總數(shù)写妥。

回頁(yè)首

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

您現(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)行索引器來(lái)創(chuàng)建索引。

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

$ 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ù)只對(duì)部分索引進(jìn)行重構(gòu)。

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

清單 11. 用 search 測(cè)試索引

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

回頁(yè)首

編寫(xiě)代碼

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

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

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;

?>

要測(cè)試代碼雳灵,需要為 Sphinx 創(chuàng)建 log 目錄棕所,啟動(dòng) searchd,然后運(yùn)行 PHP 應(yīng)用程序悯辙,如下所示:

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

$ 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é)果利于對(duì)冗長(zhǎng)的結(jié)果列表分頁(yè)谆棱。請(qǐng)查看 API 調(diào)用 SetLimits()快压。一個(gè)分頁(yè)示例是用 $cl->SetLimits( ( $page - 1 ) * SPAN, SPAN ) 調(diào)用搜索引擎返回第一批、第二批垃瞧、第三批(依此類推)SPAN 匹配結(jié)果蔫劣,這取決于顯示哪個(gè)頁(yè)面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末个从,一起剝皮案震驚了整個(gè)濱河市脉幢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嗦锐,老刑警劉巖鸵隧,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異意推,居然都是意外死亡豆瘫,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)菊值,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)外驱,“玉大人,你說(shuō)我怎么就攤上這事腻窒£怯睿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵儿子,是天一觀的道長(zhǎng)瓦哎。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么蒋譬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任割岛,我火速辦了婚禮,結(jié)果婚禮上犯助,老公的妹妹穿的比我還像新娘癣漆。我一直安慰自己,他們只是感情好剂买,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布惠爽。 她就那樣靜靜地躺著,像睡著了一般瞬哼。 火紅的嫁衣襯著肌膚如雪婚肆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天坐慰,我揣著相機(jī)與錄音旬痹,去河邊找鬼。 笑死讨越,一個(gè)胖子當(dāng)著我的面吹牛两残,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播把跨,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼人弓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了着逐?” 一聲冷哼從身側(cè)響起崔赌,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耸别,沒(méi)想到半個(gè)月后健芭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秀姐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年慈迈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片省有。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痒留,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蠢沿,到底是詐尸還是另有隱情伸头,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布舷蟀,位于F島的核電站恤磷,受9級(jí)特大地震影響面哼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扫步,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一魔策、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锌妻,春花似錦代乃、人聲如沸旬牲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)原茅。三九已至吭历,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間擂橘,已是汗流浹背晌区。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留通贞,地道東北人朗若。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像昌罩,于是被迫代替她去往敵國(guó)和親哭懈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容