對MongoDB中的數據進行搜索(1)


由於大量的數據使用MongoDB作為數據庫進行存儲,現在需要對外提供文本搜索功能,在實踐工程中,調研並嘗試了多種方案,在本文中做個記錄。

1、使用正則表達式

即使用find("textField":/搜索文本/}的方式對文本字段進行包含匹配。

這種方法的好處在於不需要進行額外的操作,現在常用的MongoDB服務器版本都能夠支持,非常方便。

但是同時,缺點也非常明顯,每次搜索必須遍歷所有的數據,消耗的時間與數據量成正比,且基本無法進行優化。在大數據量情況下每次搜索小號的時間太長,可能無法接受。

 

2、分詞存儲

基本的步驟如下:

1、使用分詞引擎對目標文本字段,例如textField進行分詞

2、將分詞的結果的每個詞按照數組的形式存儲在一個新的字段,例如searchField中

3、對searchField建立索引

4、搜索時,對請求串進行同樣的分詞,並將分詞結果作為參數進行find({ searchField: {$all: splittedTextArray} })

這種方法的好處在於,適用於各個版本的MongoDB,同時基於索引和MongoDB對於數組的專門優化,在一定數據量的情況下速度也還可以

如果要使用這種方法,需要在新數據入庫時進行處理

功能上比較簡單,很多搜索常用的需求無法實現,效率也比不上專業的搜索引擎。可以作為一種無法增加組件時的參考方案。

 

3、使用MongoDB自帶的文本搜索功能

MongoDB在較早的版本中就已經將文本搜索功能作為實驗性功能加入,當時需要使用runCommand作為系統命令進行調用。

在后來的版本中作為正式的功能引入,直接就可以使用find({"$text":{"$search":"搜索文本"})進行搜索

在搜索之前,需要對文本字段建立索引:

db.coll.createIndex( { textField: "text" } )

對於一個集合,只能建立一個索引,但是一個索引中可以包含多個字段

文本搜索的參數有如下幾個:

$search: <string>,
$language: <string>,
$caseSensitive: <boolean>,
$diacriticSensitive: <boolean> 

$search后面的關鍵詞可以有多個,並且可以使用一些符號表示與或非的關系

使用$caseSensitive設置是否區分大小寫,$language指示搜索的語言類型

$diacriticSensitive設置是否區別發音符號,例如,CAFÉ於Café是同一語義,只是重音不一樣。

並且在結果中,可以使用{score:{$meta:"textScore"}來獲得相似度

 

不過,只有在Mongodb 3.2之后的企業版中才開始加入了對中文的支持,之前或者社區的版本在建立全文索引時會自動過濾中文字符。

在Mongodb 3.2企業版中,對中文建立全文索引后,默認使用的是與英文同樣的分詞規則,即以空格與符號作為詞與詞之間分隔的界限。

所以,當使用“福爾摩斯”作為搜索詞時,無法搜索到“福爾摩斯探案全集”,只能搜索到類似“福爾摩斯(1)”之類的結果

如果想解決這種情況,可以有兩種方法:

一、在存儲文本時,自行先對該文本進行分詞處理,將需要搜索的文本加上空格即可

二、為MongoDB添加中文分詞的支持

MongoDB企業版集成了基礎技術Rosette 語義平台(RLP)根據語言來進行正規化、分詞、斷句、詞干和分詞。所以,可以使用RLP來實現對中文分詞的支持。

如果想在MongoDB中使用RLP,MongoDB需要一個RLP基礎語義組件的許可證。具體如何獲得RLP的許可證,需要聯系basistech公司。

當從basistech公司的郵件中獲取了RLP證書文件(rlp-license.xml)后,解壓拷貝到對應的目錄中

<BT_ROOT>/rlp/rlp/licenses

然后使用參數指定該目錄,重啟MongoDB即可

--basisTechRootDirectory=<BT_ROOT>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM