MeiliSearch基本用法
MeiliSearch(網稱 美麗搜尋)
前言
讓我玩了接近4個月的套件, 讓我踩雷滿滿的套件, 還要應付User腦洞大開的奇幻冒險, 怎麼可以不留下記錄呢? 但相比其他幾套知名的開源全文檢索套件來說, 這套真的比較輕量也比較簡單
何為MeiliSearch
MeiliSearch 是一個輕量級的現成全文檢索套件, 使用RESTful
搜尋API即可使用, 並支援各大系統(Windows、MacOS、Linux), 且是 Open Source所以不必擔心商業授權問題
而官方也有提供 MeiliSearch Cloud
的付費方案, 讓其使用者可以不用架設自己的Server環境也能享有全文檢索的功能
至於為何檔案這麼小, 卻又很快速呢?
據官方文件說明, MeiliSearch在第一次啟動的時候就會自動建立Database, 其檔案在根目錄的data.ms
的檔案夾內, 而這類Database引擎則是 Lightning Memory-Mapped Database(LMDB)
, 官方認為LMDB
是性能、穩定性和特性的最佳組合
- 可以在建立時使用
Cli
指令去更改DB的存放路徑-db-path
, 或使用Docker建立LMDB
是用C語言撰寫的事物型鍵值儲存,是為OpenLDAP開發的,具有ACID屬性
有那些功能?
-
Typo tolerance
錯字容錯率 -
Custom ranking
自定義搜尋時關聯性及先後順序 -
Stop words
停用字 -
Highlighting
搜尋結果中凸顯的搜索關鍵字 -
Synonyms
同義詞 -
Filtering
篩選器 -
Sorting
將搜尋結果排序 -
Search preview
簡單的預覽頁面還有更細部的功能, 之後我只會講到我用過的功能
基本使用方式
安裝方式(以Windows為例)
-
透過
cURL
安裝1 2 3 4 5 6 7
# Install Meilisearch curl -L <https://install.meilisearch.com> | sh # Launch Meilisearch ./meilisearch
-
使用 Docker 安裝(我個人是比較推薦這種方式,因為比較方便)
1 2 3 4 5 6 7 8 9
# Fetch the latest version of Meilisearch image from DockerHub docker pull getmeili/meilisearch:v1.0 # Launch Meilisearch in development mode with a master key docker run -it --rm \ -p 7700:7700 \ -e MEILI_ENV='development' \ -v $(pwd)/meili_data:/meili_data \ getmeili/meilisearch:v1.0
-
將Source Code Clone下來自行編譯(可能需要額外安裝
Rust
,cargo
等語言或套件)1 2 3 4 5 6 7 8 9 10 11 12 13 14
git clone https://github.com/meilisearch/meilisearch cd meilisearch git checkout latest # Update the rust toolchain to the latest version rustup update # Compile the project cargo build --release # Execute the server binary ./target/release/meilisearch
-
下載官方已打包好的執行檔
選擇好想要放的路徑及位置即可
-
建議要建立的硬體設備或是虛擬環境 至少要 2 cores/Ram 16G 以上 會較順暢
因為如果沒有額外設定的話, 預設Ram的使用率是該設備的2/3可用的RAM 及 1/2 可用的線程
曾經我就是用了Azure VM 最低配置去跑, 結果每1.2天就要重開執行檔, 3~5天要重開機一次
-
-
也支援各種雲端服務
- AWS
- Azure
- DigitalOcean
- GCP
- Koyeb
- Qovery
- Railway
注意!! 如果曾經用過此套件 版本為
0.X.XX
版的, 這裡1.0.0
版本沒辦法直接用喔, 因為他們有說大版更會 Breaking changes, 而下一次則是在2.0.0
版本的時候解決方法則是匯出所有Database內的資料再匯入新版本的
使用方法(以執行檔為例)
-
到放執行檔的File內後直接執行
1 2 3
cd D:/MeiliSearchDemo .\meilisearch-windows-amd64.exe
首次執行會自動產生Database相關檔案
而
1.0.0
版本開始 如果沒有加Master Key
它則會提醒, 並提供一組雜湊值建議都使用
Master Key
來保護自行設定的MeiliSearch1 2 3 4
cd D:/MeiliSearchDemo # `--master-key`是設定密鑰的CLI .\meilisearch-windows-amd64.exe --master-key="MASTER_KEY"
執行完成後, MeiliSearch就開始Run起來了,預設的Port都是7700,且MeiliSearch有提供簡易預覽可以到
localhost:7700
查看想要更改port及Http位址的話, 需要使用到
--http-addr
的CLI.\meilisearch-windows-amd64.exe --master-key="MASTER_KEY" --http-addr="127.0.0.1:2023"
-
增加索引內容
-
在需要使用的專案上, 開啟nuget搜尋
Meilisearch
或打開Terminal鍵入1
dotnet add package Meilisearch
-
先建立想要索引的欄位Model(這些欄位是可以自定義的)
1 2 3 4 5 6 7 8 9
public class Movie { // 如果有設定Id這個欄位,則MeiliSearch會自動判斷為PKey,有多個的話則不會,可以自行指定要那個欄位為PKey public int Id { get; set; } public string Title { get; set; } public string Poster { get; set; } public string Overview { get; set; } public IEnumerable<string> Genres { get; set; } }
-
增加索引的方法
1 2 3 4 5 6 7 8 9 10 11 12 13
public async Task CreateDocumentAsync() { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; string jsonString = await File.ReadAllTextAsync("Models/Database/movies.json"); var movies = JsonSerializer.Deserialize<IEnumerable<Movie>>(jsonString, options); // 如果index沒有建立過,在此會自動建立起來,如果已有此index,則會讀取相關內容 var index = client.Index("movies"); // 此方法即是增加Document,也就是增加要被索引的內容 await index.AddDocumentsAsync(movies); }
-
-
如何搜索
1 2 3 4 5 6 7 8 9 10 11 12 13
public async Task QueryAsync(string? keyword) { // 獲取要搜尋的Index索引 var index = client.Index("movies"); // 使用SearchAsync方法來搜尋鍵入的關鍵字 var movies = await index.SearchAsync<Movie>(keyword); // 搜尋與索引內容相關的都在Hits內, 而上一層有其他欄位(EX: query => 輸入的關鍵字, limit => 最多獲取的筆數, offset => 跳過的筆數) foreach (var movie in movies.Hits) { Console.WriteLine(movie.Title); } }
-
完整範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
public class Program { public MeilisearchClient client = new MeilisearchClient("http://127.0.0.1:7700", "jdWLTzfPHZK46YB8aQOXEPPD8RrPkU0E2505ixbMco8"); public static void Main(string[] args) { var p = new Program(); Console.WriteLine("Wait for create Document..."); p.CreateDocumentAsync().Wait(); Console.WriteLine("Input Your Search Keyword:"); var keyword = Console.ReadLine(); Console.WriteLine("================================="); p.QueryAsync(keyword).Wait(); Console.ReadKey(); } public async Task CreateDocumentAsync() { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; string jsonString = await File.ReadAllTextAsync("Models/Database/movies.json"); var movies = JsonSerializer.Deserialize<IEnumerable<Movie>>(jsonString, options); // 如果index沒有建立過,在此會自動建立起來,如果已有此index,則會讀取相關內容 var index = client.Index("movies"); // 此方法即是增加Document,也就是增加要被索引的內容 await index.AddDocumentsAsync(movies); // 取得當前新增後的Task,裡面會有當前狀態 var task = await client.GetTaskAsync(0); Console.WriteLine("Create Result:" + task.Status); } public async Task QueryAsync(string? keyword) { // 獲取要搜尋的Index索引 var index = client.Index("movies"); // 使用SearchAsync方法來搜尋鍵入的關鍵字 var movies = await index.SearchAsync<Movie>(keyword); // 搜尋與索引內容相關的都在Hits內, 而上一層有其他欄位(EX: query => 輸入的關鍵字, limit => 最多獲取的筆數, offset => 跳過的筆數) foreach (var movie in movies.Hits) { Console.WriteLine(movie.Title); } } }
程式執行結果
MeiliSearch提供的簡易Demo結果