搜索查詢力爭做到簡單明了,和目前最流行的搜索引擎做法極為相似,并不需要過多額外的修飾或語法。
您只要把您打算搜索的短語或關(guān)鍵詞列出來即可,建議用空格連接多個(gè)詞;在此基礎(chǔ)上還支持字段搜索、 布爾搜索、精確搜索、相鄰位置搜索等。
1. 典型搜索語句正如上面所講,僅僅用空格把搜索詞、名子連接起來的方式最為常用。內(nèi)部默認(rèn)采用 AND
規(guī)則, 也就是說要求列出來的關(guān)鍵詞(分詞之后)全部匹配,如果您通過 XSSearch::setFuzzy 開啟了模糊匹配,那么相當(dāng)于采用 OR
規(guī)則,只要其中一個(gè)關(guān)鍵詞匹配即可。
剛剛說的這種搜索的是索引數(shù)據(jù)庫的“混合區(qū)”,即類型為 body
的字段以及索引方式為 mixed
或
both
的字段。如果某個(gè)字段的索引方式為 self
或 both
,那么還可以指定為字段檢索,
也就是要求這個(gè)字段匹配指定的關(guān)鍵詞,用法為格式為 “字段名:關(guān)鍵詞”。
Note: 搜索語句最大支持長度為 80 字節(jié)(每一個(gè)漢字占 3 字節(jié)),此規(guī)則同時(shí)適用于XSSearch::search 和 XSSearch::count 的
$query
參數(shù)。
搜索語句舉例如下:
$search->search('上海人民公園'); // 檢索 body 型字段及混合區(qū)
$search->search('上海 人民公園'); // 用空格連接 2 個(gè)關(guān)鍵詞, 這種情況比上面的用法更明確
$search->search('subject:上海 人民公園'); // 特別要求 subject 字段包含 "上海"
$search->setFuzzy()->search('上海公園'); // 開啟模糊搜索,搜索 "上海" 或 "公園"
2. 布爾搜索Tip: 從 1.3.0 版本起,允許使用空搜索條件進(jìn)行搜索了,其含義相當(dāng)于全部匹配
出于高級(jí)搜索的需求,我們的搜索語句還全面支持布爾操作,并且像數(shù)學(xué)運(yùn)算一樣支持括號(hào)操作以明確關(guān)系。
默認(rèn)情況,系統(tǒng)采用“并且”關(guān)系,即您輸入的多個(gè)詞語(空格分開或系統(tǒng)自動(dòng)切分以后)必須全部包含。 您也可以通過 AND
將這些關(guān)鍵詞顯式的強(qiáng)制要求全部出現(xiàn)。相應(yīng)的,如果您需要只包括其中一個(gè)詞即可, 那么用
OR
將它們連接起來。更有趣的是,如果有些情況您只想要其中的一個(gè)詞,并且不要兩者同時(shí)出現(xiàn), 那么就用 XOR
連接。參看下面的例子:
Note: 表達(dá)布爾關(guān)系的關(guān)鍵字必須全部大寫,即:XOR, OR, AND
$search->search('杭州 西湖');
$search->search('杭州 AND 西湖'); // 這兩者效果是相同的
$search->setFuzzy()->search('杭州 西湖');
$search->search('杭州 OR 西湖'); // 這兩者效果相同,都是只要求匹配其中一個(gè)
$search->search('杭州 XOR 西湖'); // 表示必須包含其中一個(gè)詞,并且不允許同時(shí)包含這兩個(gè)詞。
如果您發(fā)現(xiàn)搜索結(jié)果中,有某一類信息是您不希望看見的,而且這些信息都包含特定的關(guān)鍵詞,那么請(qǐng)用減號(hào)或NOT
語法,就可以去除所有這些含有特定關(guān)鍵詞的網(wǎng)頁。例如,搜索 “神雕俠侶”,希望是關(guān)于武俠小說方面 的內(nèi)容,卻發(fā)現(xiàn)很多關(guān)于電視劇方面的網(wǎng)頁。這時(shí)希望排除所有包含“電視劇”的搜索結(jié)果。
Note: 前一個(gè)關(guān)鍵詞和減號(hào)之間必須有空格分開,否則會(huì)被當(dāng)連字符處理,減號(hào)和后一個(gè)關(guān)鍵詞之間不能有空格。
$search->search('神雕俠侶 -電視劇'); // 正確用法1
$search->search('神雕俠侶 NOT 電視劇'); // 正確用法2
$search->search('神雕俠侶-電視劇'); // 不符合預(yù)期目的
$search->search('神雕俠侶 - 電視劇'); // 不符合預(yù)期目的
就像數(shù)學(xué)表達(dá)式中,括號(hào)具有顯式的優(yōu)先級(jí),如果您需要非常復(fù)雜的搜索條件,就采用括號(hào)表達(dá)式來組合上述的條件。
// 要求結(jié)果包含 “杭州+西湖” 或 “杭州 + 西溪濕地”,并且不能包含 “汽車 火車”
$search->search('((杭州 AND 西湖) OR (杭州 AND 西溪濕地)) NOT (汽車 火車)');
3. 精確搜索Tip: 在組合關(guān)鍵中允許嵌入字段搜索的語法。如:
subject:上海 OR subject:公園
在項(xiàng)目字段設(shè)計(jì)中有一個(gè)選項(xiàng) phrase
如果設(shè)為 yes
將在索引數(shù)據(jù)庫中保存關(guān)鍵詞的位置信息,
因而我們可以在搜索時(shí)利用這些位置信息實(shí)現(xiàn)精確搜索。
Info: 項(xiàng)目中類型為
title
、body
的字段默認(rèn)已開啟此項(xiàng),此外這個(gè)選項(xiàng)也僅針對(duì)使用內(nèi)置分詞器的字段有效。 對(duì)于phrase
設(shè)為no
或用其它分詞器的字段來說這項(xiàng)功能無效。
如果輸入的查詢?cè)~較長,在經(jīng)過系統(tǒng)詞法分析后,給出的搜索結(jié)果中的查詢?cè)~,可能是拆分的。 如果您對(duì)這種情況不滿意,可以嘗試給查詢短句加上雙引號(hào),搜索結(jié)果就會(huì)要求詞按順序匹配。
$search->search('上??萍即髮W(xué)');// 這時(shí)內(nèi)部把搜索語句切割為:上海+科技+大學(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
語法來進(jìn)行搜索,默認(rèn)要求它們的距離不超過 10
。您還可以在
NEAR
后加上 /n
表示 具體的距離要求,n
是整數(shù),這兒的距離指的是分詞后的
序號(hào)距離。
$search->search('杭州 NEAR 西湖'); // 要求結(jié)果中出現(xiàn) "杭州" 和 "西湖",并且距離不超過 10 個(gè)詞
$search->search('杭州 NEAR/5 西湖'); // 要求它們距離不超過 5個(gè)詞
如果您還希望檢索結(jié)果中詞匯出現(xiàn)的順序與您的輸入順序一致,只要將 NEAR
換成 ADJ
即可,
注意這些語法詞和布爾搜索一樣,均必須全部大寫。
$search->search('杭州 ADJ 西湖'); // 要求結(jié)果中先出現(xiàn) "杭州" 再出現(xiàn) "西湖",并且距離不超過 10 個(gè)詞
$search->search('杭州 ADJ/3 西湖'); // 要求它們距離不超過 3個(gè)詞
4. 其它搜索語句修飾
前面還有提到一些附加的搜索語句修飾,這些操作不能直接寫進(jìn) Query
語句,只能過過相應(yīng)的 API
來完成。
通過 XSSearch::addRange 我們可以在搜索中,針對(duì)某個(gè)字段的值增加區(qū)間條件過濾。該方法接受三個(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();
通過 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();
5. 查看搜索語句的分析結(jié)果Note: 這些修飾不能應(yīng)用到快捷搜索中,也就是說不能直接把
Query
語句傳遞給 XSSearch::search。 您必須用 XSSearch::setQuery 設(shè)置搜索語句,再用不帶參數(shù)的調(diào)用search
或count
方法。區(qū)間搜索默認(rèn)用的是字節(jié)序比較,如果您希望將字段值以數(shù)字方式比較大小,請(qǐng)將字段的類型設(shè)置為
numeric
。
通過 XSSearch::setQuery 設(shè)置了搜索語句后,您可以調(diào)用 XSSearch::getQuery 查看您的搜索語句 在內(nèi)部的分析結(jié)果,常用于 DEBUG
。此外這兩個(gè)方法也可以通過魔術(shù)屬性
XSSearch::query 來訪問。
// 設(shè)置搜索語句方法1:
$search->setQuery('神雕俠侶 -電視劇');
// 設(shè)置搜索語句方法2:
$search->query = '神雕俠侶 -電視劇';
// 查看搜索語句解析結(jié)果方法1:// 不帶參數(shù),輸出:Xapian::Query((神雕俠侶:(pos=1) AND_NOT 電視劇:(pos=2)))
echo $search->getQuery();
// 帶參數(shù),則解析新語句,輸出:Xapian::Query((杭州:(pos=1) AND 西湖:(pos=2)))
echo $search->getQuery('杭州 西湖');
// 查看搜索語句解析結(jié)果方法2:
// 相當(dāng)于不帶參數(shù)的調(diào)用 getQuery()
echo $search->query;
更多建議: