構(gòu)建搜索語(yǔ)句

2019-08-14 14:11 更新

搜索查詢力爭(zhēng)做到簡(jiǎn)單明了,和目前最流行的搜索引擎做法極為相似,并不需要過(guò)多額外的修飾或語(yǔ)法。

您只要把您打算搜索的短語(yǔ)或關(guān)鍵詞列出來(lái)即可,建議用空格連接多個(gè)詞;在此基礎(chǔ)上還支持字段搜索、 布爾搜索、精確搜索、相鄰位置搜索等。

1. 典型搜索語(yǔ)句

正如上面所講,僅僅用空格把搜索詞、名子連接起來(lái)的方式最為常用。內(nèi)部默認(rèn)采用 AND 規(guī)則, 也就是說(shuō)要求列出來(lái)的關(guān)鍵詞(分詞之后)全部匹配,如果您通過(guò) XSSearch::setFuzzy 開(kāi)啟了模糊匹配,那么相當(dāng)于采用 OR 規(guī)則,只要其中一個(gè)關(guān)鍵詞匹配即可。

剛剛說(shuō)的這種搜索的是索引數(shù)據(jù)庫(kù)的“混合區(qū)”,即類型為 body 的字段以及索引方式為 mixed 或  both 的字段。如果某個(gè)字段的索引方式為 self 或 both,那么還可以指定為字段檢索, 也就是要求這個(gè)字段匹配指定的關(guān)鍵詞,用法為格式為 “字段名:關(guān)鍵詞”。

Note: 搜索語(yǔ)句最大支持長(zhǎng)度為 80 字節(jié)(每一個(gè)漢字占 3 字節(jié)),此規(guī)則同時(shí)適用于XSSearch::search 和  XSSearch::count 的 $query 參數(shù)。

搜索語(yǔ)句舉例如下:

$search->search('上海人民公園'); // 檢索 body 型字段及混合區(qū)
$search->search('上海 人民公園'); // 用空格連接 2 個(gè)關(guān)鍵詞, 這種情況比上面的用法更明確
$search->search('subject:上海 人民公園'); // 特別要求 subject 字段包含 "上海"
$search->setFuzzy()->search('上海公園'); // 開(kāi)啟模糊搜索,搜索 "上海" 或 "公園"

Tip: 從 1.3.0 版本起,允許使用空搜索條件進(jìn)行搜索了,其含義相當(dāng)于全部匹配

2. 布爾搜索

出于高級(jí)搜索的需求,我們的搜索語(yǔ)句還全面支持布爾操作,并且像數(shù)學(xué)運(yùn)算一樣支持括號(hào)操作以明確關(guān)系。

多個(gè)詞語(yǔ)之間的“并且”、“或者”、“異或”關(guān)系

默認(rèn)情況,系統(tǒng)采用“并且”關(guān)系,即您輸入的多個(gè)詞語(yǔ)(空格分開(kāi)或系統(tǒng)自動(dòng)切分以后)必須全部包含。 您也可以通過(guò) AND 將這些關(guān)鍵詞顯式的強(qiáng)制要求全部出現(xiàn)。相應(yīng)的,如果您需要只包括其中一個(gè)詞即可, 那么用  OR 將它們連接起來(lái)。更有趣的是,如果有些情況您只想要其中的一個(gè)詞,并且不要兩者同時(shí)出現(xiàn), 那么就用 XOR 連接。參看下面的例子:

Note: 表達(dá)布爾關(guān)系的關(guān)鍵字必須全部大寫(xiě),即:XOR, OR, AND

$search->search('杭州 西湖');
$search->search('杭州 AND 西湖'); // 這兩者效果是相同的
$search->setFuzzy()->search('杭州 西湖');
$search->search('杭州 OR 西湖');  // 這兩者效果相同,都是只要求匹配其中一個(gè)
$search->search('杭州 XOR 西湖'); // 表示必須包含其中一個(gè)詞,并且不允許同時(shí)包含這兩個(gè)詞。

要求搜索結(jié)果中不含特定關(guān)鍵詞

如果您發(fā)現(xiàn)搜索結(jié)果中,有某一類信息是您不希望看見(jiàn)的,而且這些信息都包含特定的關(guān)鍵詞,那么請(qǐng)用減號(hào)或NOT 語(yǔ)法,就可以去除所有這些含有特定關(guān)鍵詞的網(wǎng)頁(yè)。例如,搜索 “神雕俠侶”,希望是關(guān)于武俠小說(shuō)方面 的內(nèi)容,卻發(fā)現(xiàn)很多關(guān)于電視劇方面的網(wǎng)頁(yè)。這時(shí)希望排除所有包含“電視劇”的搜索結(jié)果。

Note: 前一個(gè)關(guān)鍵詞和減號(hào)之間必須有空格分開(kāi),否則會(huì)被當(dāng)連字符處理,減號(hào)和后一個(gè)關(guān)鍵詞之間不能有空格。

$search->search('神雕俠侶 -電視劇'); // 正確用法1
$search->search('神雕俠侶 NOT 電視劇'); // 正確用法2
$search->search('神雕俠侶-電視劇'); // 不符合預(yù)期目的
$search->search('神雕俠侶 - 電視劇'); // 不符合預(yù)期目的

組合關(guān)系的括號(hào)表達(dá)式

就像數(shù)學(xué)表達(dá)式中,括號(hào)具有顯式的優(yōu)先級(jí),如果您需要非常復(fù)雜的搜索條件,就采用括號(hào)表達(dá)式來(lái)組合上述的條件。

// 要求結(jié)果包含 “杭州+西湖” 或 “杭州 + 西溪濕地”,并且不能包含 “汽車 火車”
$search->search('((杭州 AND 西湖) OR (杭州 AND 西溪濕地)) NOT (汽車 火車)');

Tip: 在組合關(guān)鍵中允許嵌入字段搜索的語(yǔ)法。如:subject:上海 OR subject:公園

3. 精確搜索

在項(xiàng)目字段設(shè)計(jì)中有一個(gè)選項(xiàng) phrase 如果設(shè)為 yes 將在索引數(shù)據(jù)庫(kù)中保存關(guān)鍵詞的位置信息, 因而我們可以在搜索時(shí)利用這些位置信息實(shí)現(xiàn)精確搜索。

Info: 項(xiàng)目中類型為 titlebody 的字段默認(rèn)已開(kāi)啟此項(xiàng),此外這個(gè)選項(xiàng)也僅針對(duì)使用內(nèi)置分詞器的字段有效。 對(duì)于 phrase 設(shè)為 no 或用其它分詞器的字段來(lái)說(shuō)這項(xiàng)功能無(wú)效。

使用雙引號(hào)進(jìn)行精確匹配

如果輸入的查詢?cè)~較長(zhǎng),在經(jīng)過(guò)系統(tǒng)詞法分析后,給出的搜索結(jié)果中的查詢?cè)~,可能是拆分的。 如果您對(duì)這種情況不滿意,可以嘗試給查詢短句加上雙引號(hào),搜索結(jié)果就會(huì)要求詞按順序匹配。

$search->search('上海科技大學(xué)');// 這時(shí)內(nèi)部把搜索語(yǔ)句切割為:上海+科技+大學(xué),要求搜索結(jié)果同時(shí)包含這三個(gè)詞即可,
// 但不要求它們的出現(xiàn)順序,有可能先出現(xiàn)”科技“再出現(xiàn)”上?!?,也有可能這三個(gè)詞離得很遠(yuǎn)。
 $search->search('"上??萍即髮W(xué)"');// 加上引號(hào)后,要求搜索結(jié)果必須依次出現(xiàn)”上海+科技+大學(xué)“,要顯得精準(zhǔn)很多。

索引詞之間的距離查詢

如果您希望輸入的多個(gè)關(guān)鍵詞之間的在匹配結(jié)果中的位置距離不要太遠(yuǎn),那么可以使用 NEAR 語(yǔ)法來(lái)進(jìn)行搜索,默認(rèn)要求它們的距離不超過(guò) 10。您還可以在  NEAR 后加上 /n 表示 具體的距離要求,n 是整數(shù),這兒的距離指的是分詞后的 序號(hào)距離。

$search->search('杭州 NEAR 西湖'); // 要求結(jié)果中出現(xiàn) "杭州" 和 "西湖",并且距離不超過(guò) 10 個(gè)詞
$search->search('杭州 NEAR/5 西湖'); // 要求它們距離不超過(guò) 5個(gè)詞

如果您還希望檢索結(jié)果中詞匯出現(xiàn)的順序與您的輸入順序一致,只要將 NEAR 換成 ADJ 即可, 注意這些語(yǔ)法詞和布爾搜索一樣,均必須全部大寫(xiě)。

$search->search('杭州 ADJ 西湖'); // 要求結(jié)果中先出現(xiàn) "杭州" 再出現(xiàn) "西湖",并且距離不超過(guò) 10 個(gè)詞
$search->search('杭州 ADJ/3 西湖'); // 要求它們距離不超過(guò) 3個(gè)詞
4. 其它搜索語(yǔ)句修飾

前面還有提到一些附加的搜索語(yǔ)句修飾,這些操作不能直接寫(xiě)進(jìn) Query 語(yǔ)句,只能過(guò)過(guò)相應(yīng)的 API 來(lái)完成。

字段值區(qū)間搜索

通過(guò) XSSearch::addRange 我們可以在搜索中,針對(duì)某個(gè)字段的值增加區(qū)間條件過(guò)濾。該方法接受三個(gè)參數(shù), 第一參數(shù)  $field 為字段名稱,后面兩個(gè)參數(shù)依次是 $from 起始值,$to 結(jié)束值。假設(shè)該字段的值為  $value,那么要求 $value > $from && $value <= $to 才符合條件,其中如果有一個(gè)設(shè)為 null, 則會(huì)自動(dòng)將區(qū)間轉(zhuǎn)換為單向比較。

以前面提到的 demo 項(xiàng)目中的 chrono 字段為例,參看下面代碼及注釋:

$from = strtotime("2011-1-1"); // 起始時(shí)間 2011年1月1日
$to = strtotime("2011-9-1"); // 結(jié)束時(shí)間 2011年9月1日
// 1. <= $to: 要求結(jié)果的時(shí)間必須在 2011-9-1 之前,并且包含 2011-9-1
$docs = $search->setQuery('杭州')->addRange('chrono', null, $to)->search(); 
// 2. >= $from: 要求結(jié)果的時(shí)間必須在 2011-1-1 之后,并且包含 2011-1-1
$docs = $search->setQuery('杭州')->addRange('chrono', $from, null)->search(); 
// 3. > $from && <= $to: 要求結(jié)果的時(shí)間必須在 2011-1-1 之后 并且 2011-9-1 之前
$docs = $search->setQuery('杭州')->addRange('chrono', $from, $to)->search();

按字段索引詞加權(quán)

通過(guò) XSSearch::addWeight 我們可以針對(duì)某個(gè)字段添加權(quán)重索引詞。該字段是否包含這個(gè)詞 都不影響搜索匹配結(jié)果,但如果包含會(huì)參與計(jì)算結(jié)果權(quán)重,使結(jié)果的相關(guān)度更高。常用于針對(duì)某一類 數(shù)據(jù)提升搜索結(jié)果排序位置。

// 搜索包含 "杭州" 的結(jié)果,并且提升 subject 字段包含 "西湖" 的數(shù)據(jù)的排序
$docs = $search->setQuery('杭州')->addWeight('subject', '西湖')->search();

Note: 這些修飾不能應(yīng)用到快捷搜索中,也就是說(shuō)不能直接把 Query 語(yǔ)句傳遞給  XSSearch::search。 您必須用 XSSearch::setQuery 設(shè)置搜索語(yǔ)句,再用不帶參數(shù)的調(diào)用 search 或  count 方法。

區(qū)間搜索默認(rèn)用的是字節(jié)序比較,如果您希望將字段值以數(shù)字方式比較大小,請(qǐng)將字段的類型設(shè)置為numeric。

5. 查看搜索語(yǔ)句的分析結(jié)果

通過(guò) XSSearch::setQuery 設(shè)置了搜索語(yǔ)句后,您可以調(diào)用 XSSearch::getQuery 查看您的搜索語(yǔ)句 在內(nèi)部的分析結(jié)果,常用于 DEBUG。此外這兩個(gè)方法也可以通過(guò)魔術(shù)屬性  XSSearch::query 來(lái)訪問(wèn)。

// 設(shè)置搜索語(yǔ)句方法1:
$search->setQuery('神雕俠侶 -電視劇'); 
// 設(shè)置搜索語(yǔ)句方法2:
$search->query = '神雕俠侶 -電視劇'; 
// 查看搜索語(yǔ)句解析結(jié)果方法1:// 不帶參數(shù),輸出:Xapian::Query((神雕俠侶:(pos=1) AND_NOT 電視劇:(pos=2)))
echo $search->getQuery(); 
// 帶參數(shù),則解析新語(yǔ)句,輸出:Xapian::Query((杭州:(pos=1) AND 西湖:(pos=2)))
echo $search->getQuery('杭州 西湖'); 
 
// 查看搜索語(yǔ)句解析結(jié)果方法2:
// 相當(dāng)于不帶參數(shù)的調(diào)用 getQuery()
echo $search->query;

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)