相見恨晚!開源的傻瓜搜尋引擎,幫你快速實現搜尋功能

HelloGitHub發表於2021-08-13

這是我參與8月更文挑戰的第5天,活動詳情檢視:8月更文挑戰

傻瓜一詞借鑑自傻瓜相機,又稱輕便相機、全自動相機,通常指容易操作針對一般人而設計的小型全自動相機。

在 HelloGitHub 找到有趣、入門級的開源專案,大家好我是滷蛋。說到開源搜尋引擎第一個想到的應該是鼎鼎大名的 ElasticSearch,但 ES 對於個人專案有些重。

今天給大家帶來一款輕盈、人人都會用的開源傻瓜搜尋引擎——MeiliSearch

github.com/meilisearch…

在介紹 MeiliSearch 的功能之前,我想先聊下我是怎麼找到它並喜歡上它的。

我的要求並不高

我開發的 HelloGitHub 小程式:支援關鍵字搜尋往期月刊中的開源專案。

小程式的搜尋功能是用 Rust 寫的開源搜尋引擎 Sonic,它雖然搜尋速度快但使用過程中發現:

  • 不支援中文分詞,導致搜尋結果較差
  • 沒有官方的 Python 客戶端,三方開源客戶端問題較多
  • 搜尋返回的結果僅有 ID,需要再去資料庫關聯其他資料

這些問題直接影響了搜尋的體驗,讓我十分苦惱一邊看搜尋相關的知識,另外也在尋找新的開源解決方案。想找一個:

部署+配置簡單、支援中文分詞、搜尋速度快、輕量級開源搜尋引擎專案。

俗稱:傻瓜中文搜尋引擎。

它有個美麗的名字

它有個“美麗”(meili)的名字「MeiliSearch」,同樣是用 Rust 寫的開源搜尋引擎,支援:

概述功能:搜尋速度快、全文搜尋、支援漢字、容易安裝和維護,這不就是我在找的:傻瓜中文搜尋引擎嗎?

我已經摩拳擦掌的躍躍欲試了,話不多說搞起!

簡單的開始

紙上得來終覺淺,得上手試試效果。

1、安裝和啟動

Linux & Mac OS 的一鍵安裝和啟動的命令:

curl -L https://install.meilisearch.com | sh
./meilisearch
複製程式碼

這個安裝夠不夠傻瓜? 啟動成功如下圖:

用瀏覽器訪問:http://127.0.0.1:7700/ 就可以看到 MeiliSearch 提供的 Web 搜尋頁面。我提前寫入了一些資料,用來演示搜尋:

2、基本操作

MeiliSearch 就是一個搜尋的服務,提供 RESTful API 通訊協議更加通用,官方提供了多種程式語言的客戶端:

  • JavaScript
  • Python
  • PHP
  • Go
  • ...

後面的演示將採用 Python 程式碼作為示例,安裝 Python SDK:

# 要求 Python3.6+
pip3/pip install meilisearch
複製程式碼

用 Python 實現連線、寫入、查詢、刪除等基本操作:

import meilisearch

client = meilisearch.Client('http://127.0.0.1:7700', 'masterKey') # masterKey 是密碼

# index 相當於資料庫的表
index = client.index('books')

# 準備寫入搜尋的資料
documents = [
  { 'book_id': 123,  'title': 'Pride and Prejudice' },
  { 'book_id': 456,  'title': 'Le Petit Prince' },
  { 'book_id': 1,    'title': 'Alice In Wonderland' },
  { 'book_id': 1344, 'title': 'The Hobbit' },
  { 'book_id': 4,    'title': 'Harry Potter and the Half-Blood Prince' },
  { 'book_id': 42,   'title': 'The Hitchhiker\'s Guide to the Galaxy' }
]
# 刪:清空指定 index
index.delete_all_documents()

# 寫:
result = index.add_documents(documents) 
# 該引擎會根據寫入資料 ID 做替換或者新增的操作
# 寫入後並不代表搜尋引擎處理完成,可以檢視返回 updateId 的狀態
index.get_update_status(result.get('updateId'))
# enqueued, processed or failed 三種狀態(processed 代表完成)

# 查:
index.search('harry pottre')
# 結果:
# 包含豐富的欄位
"""
{
  // 命中的結果
  "hits" => [{
    "book_id" => 4,
    "title" => "Harry Potter and the Half-Blood Prince"
  }],
  // 頁
  "offset" => 0,
  // 每頁條數
  "limit" => 20,
  // 處理耗時
  "processingTimeMs" => 1,
  // 查詢的內容
  "query" => "harry pottre"
}
"""
複製程式碼

至此已經實現了搜尋的最基本的功能,但探索不止於此。

3、優化搜尋效果

MeiliSearch 可通過配置規則來提高搜尋結果:

  • synonyms:同義詞
  • stopWords:停用詞(為節省儲存空間和提高搜尋效率,自動過濾掉某些字或詞)
  • rankingRules:排序規則
  • ...

可以用 Python 客戶端更新 MeiliSearch 配置,示例程式碼:

# 停用詞
client.index('movies').update_settings({
  'stopWords': [
      'the',
      'a',
      'an'
  ],
})
# 排序規則
client.index('movies').update_ranking_rules([
    "typo",
    "words",
    "proximity",
    "attribute",
    "wordsPosition",
    "exactness",
    "asc(publish_time)",
    "desc(watch)"
])
# 檢視 stop words
client.index('movies').get_stop_words()
# 重置設定
# index.reset_settings()
# 除了搜尋其它操作都是非同步,會直接返回一個 updateId 需要通過 ID 查詢處理狀態
# wait_for_pending_update 可阻塞等待處理結果
複製程式碼

這些設定可以有效的提高搜尋效果,比如使用停用詞之前,搜尋“開源的書籍”命中不了“開源書籍”,加了停用詞即可命中,因為匹配時忽略了輸入內容包含的停用詞(無用詞)。

說一個我遇到的坑,我測試搜尋效果時發現:go 搜不到,但是 golang 就可以搜尋到,排查了半天最後發現是因為 go 在上面的停用詞字典中?

另外,功能上對比 sonic 沒有詞聯想(suggest),可以通過新建 index+searchableAttributes 實現。

同義詞集合我沒有找到,如果大家有現成的 中/英文 同義詞詞典,歡迎留言告訴我~感謝

4、部署

MeiliSearch 部署很簡單,增加到系統的 systemd 服務就行了。

cat << EOF > /etc/systemd/system/meilisearch.service
[Unit]
Description=MeiliSearch
After=systemd-user-sessions.service

[Service]
Type=simple
ExecStart=/usr/bin/meilisearch --http-addr 127.0.0.1:7700 --env production --master-key xxxxxx

[Install]
WantedBy=default.target
EOF

# Set the service meilisearch
systemctl enable meilisearch

# Start the meilisearch service
systemctl start meilisearch

# Verify that the service is actually running
systemctl status meilisearch
複製程式碼

但部署正式環境,需要注意以下幾點:

  1. 生產環境必須設定密碼,開發環境無強制
  2. 生產環境 Web 頁面會關閉
  3. 沒有遠端訪問和許可權控制,可以通過 Nginx 實現 IP 白名單+ Cerbot 實現 HTTPS,提高安全性
  4. 可通過 curl 地址 檢視服務狀態

以上就是我使用 MeiliSearch 的一些心得,總體給我的感覺:

  • 安裝簡單,沒有複雜的配置:省心
  • 資料寫入方便,功能豐富:傻瓜
  • 查詢快

一條命令即可啟動搜尋服務,一行程式碼實現搜尋功能,有了它我這個搜尋小白都能分分鐘實現一個搜尋服務,舒服~

愛的結晶(實戰)

我用 MeiliSearch 重寫了 HelloGitHub 小程式的搜尋功能,後端用的 FastAPI 框架。除此之外還增加了一些新功能:

  1. 熱門搜尋詞
  2. 專案詳情頁
  3. 專案映象地址提高訪問速度
  4. 新的介面

HelloGitHub 小程式第二版效果圖如下:

已上線,同名公眾號有入口。

後面計劃增加:資訊流、評論、打分、使用者系統、積分系統,因為只有我一個人開發,所以進度會很慢...但我不會半途而廢噠 ?

最後

如果說 MeiliSearch 缺點的話,我覺得搜尋準確度還有待提高,一方面我需要學習下分詞和 NLP 的一些知識,另一方面需要再熟悉下它的 API 和原理,然後再找一些詞典輔助,應該能提高準確度,但心急吃不了熱豆腐慢慢來吧。

最後,希望本文的分享有幫助到你,今天的文章就到這裡了。如果你也想分享把玩開源專案的心得,歡迎投稿原創文章給我。

優秀的開源專案像散落在海邊的貝殼,需要發現它的人。

HelloGitHub 就是拾貝者,找開源專案來 HelloGitHub 就對了!


關注 HelloGitHub 公眾號 第一時間收到更新。

還有更多開源專案的介紹和寶藏專案等待你的發現。

相關文章