構建搜索語句

2019-08-14 14:11 更新

搜索查詢力爭做到簡單明了,和目前最流行的搜索引擎做法極為相似,并不需要過多額外的修飾或語法。

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

1. 典型搜索語句

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

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

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

搜索語句舉例如下:

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

Tip: 從 1.3.0 版本起,允許使用空搜索條件進行搜索了,其含義相當于全部匹配

2. 布爾搜索

出于高級搜索的需求,我們的搜索語句還全面支持布爾操作,并且像數(shù)學運算一樣支持括號操作以明確關系。

多個詞語之間的“并且”、“或者”、“異或”關系

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

Note: 表達布爾關系的關鍵字必須全部大寫,即:XOR, OR, AND

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

要求搜索結果中不含特定關鍵詞

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

Note: 前一個關鍵詞和減號之間必須有空格分開,否則會被當連字符處理,減號和后一個關鍵詞之間不能有空格。

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

組合關系的括號表達式

就像數(shù)學表達式中,括號具有顯式的優(yōu)先級,如果您需要非常復雜的搜索條件,就采用括號表達式來組合上述的條件。

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

Tip: 在組合關鍵中允許嵌入字段搜索的語法。如:subject:上海 OR subject:公園

3. 精確搜索

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

Info: 項目中類型為 titlebody 的字段默認已開啟此項,此外這個選項也僅針對使用內置分詞器的字段有效。 對于 phrase 設為 no 或用其它分詞器的字段來說這項功能無效。

使用雙引號進行精確匹配

如果輸入的查詢詞較長,在經過系統(tǒng)詞法分析后,給出的搜索結果中的查詢詞,可能是拆分的。 如果您對這種情況不滿意,可以嘗試給查詢短句加上雙引號,搜索結果就會要求詞按順序匹配。

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

索引詞之間的距離查詢

如果您希望輸入的多個關鍵詞之間的在匹配結果中的位置距離不要太遠,那么可以使用 NEAR 語法來進行搜索,默認要求它們的距離不超過 10。您還可以在  NEAR 后加上 /n 表示 具體的距離要求,n 是整數(shù),這兒的距離指的是分詞后的 序號距離。

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

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

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

前面還有提到一些附加的搜索語句修飾,這些操作不能直接寫進 Query 語句,只能過過相應的 API 來完成。

字段值區(qū)間搜索

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

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

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

按字段索引詞加權

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

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

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

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

5. 查看搜索語句的分析結果

通過 XSSearch::setQuery 設置了搜索語句后,您可以調用 XSSearch::getQuery 查看您的搜索語句 在內部的分析結果,常用于 DEBUG。此外這兩個方法也可以通過魔術屬性  XSSearch::query 來訪問。

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

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號