Rust製の検索エンジン Tantivy は日本語でも使えた
Photo by Markus Winkler on Unsplash
Rust製の検索エンジン Tantivy を使って日本語検索してみた。
Tantivy ではTokenizerを自由に変更できるため、期待した結果を得ることができた。
Sonic ではTokenizerを変えたりすることができなかったため、日本語検索が上手く機能させることができず残念な思いをしたけれど、これでRust製の検索エンジンを使うことができるので嬉しい。
Tantivyの使い方
これまた、READMEで紹介されている例通りに行うだけ。
とりあえず動かしてみる
cargo new
(または cargo init
) しても良いのだけど、面倒なので git clone
する。
git clone --depth 1 https://github.com/tantivy-search/tantivy rust-search-tantivy
cd rust-search-tantivy
それから、
cargo run --example basic_search
他にもいろいろな例があるので、動かしてみると、使い方がわかる。
tantivy-cli で遊んでみる
tantivy-cli の README で紹介されている通りに実行していく。
cargo install tantivy-cli
curl -L -O http://fulmicoton.com/tantivy-files/wiki-articles-1000.json
tantivy new -i ./wikipedia-index
cat wiki-articles-1000.json | tantivy index -i ./wikipedia-index
du -sh wikipedia-index/ # この例では、index のサイズ(11MB)は元データ (10MB)とあまり変わらないみたい。
tantivy search -i wikipedia-index -q "barack obama"
# 以下のようにするとHTTPでAPIを叩いて検索できるようになる。素晴らしい。
tantivy serve -i wikipedia-index
日本語 Tokenizer
以下の2つのTokenizerが紹介されていた。
※ 💀更新されていない。こちらのISSUEによると、上手く動かないらしい。 ※ こちらの記事によれば、lindera は kuromoji-rs(crates.io に publish されていない) の開発を引き継いでいるとのことなので。
lindera を使うべし。
設定方法
Cargo.tomlに以下を追加して
[dependencies]
lindera-tantivy = { git = "https://github.com/ken0x0a/lindera-tantivy", branch = "chore/tantivy0.13" }
# lindera-tantivy = "1" # これだと tantivy 0.13.0 だと動かない
※ これがマージされてリリースされるまでは、自分のforkを使う必要あり。
Tokenizer を Schemaで設定して Index に登録する。
// 任意の名前
const TOKENIZER_KUROMOJI: &str = "ja_tokenizer";
// Schema で tokenizer を選択する。
let mut schema_builder = Schema::builder();
schema_builder.add_text_field(
"name",
TextOptions::default()
.set_indexing_options(
TextFieldIndexing::default()
.set_tokenizer(TOKENIZER_KUROMOJI)
.set_index_option(IndexRecordOption::WithFreqs), // IndexRecordOption も必要に応じて変える
)
.set_stored(), // 適宜、つけても消しても
);
let schema = schema_builder.build();
// Index に tokenizer を登録する
let index = Index::open_or_create(directory, schema)?; // `create_in_dir` などなど index を作れば何でも良い
// let index = Index::open_in_dir(&index_path)?; // ReadOnly
index
.tokenizers()
.register(TOKENIZER_KUROMOJI, lindera_tantivy::tokenizer::LinderaTokenizer::new("decompose", ""));
おまけ
index に登録された document 数の確認方法
let index = open_index(&index_path)?;
let meta = index.load_metas()?; // https://docs.rs/tantivy/0.13.0/tantivy/struct.Index.html#method.load_metas
let mut total_doc_count = 0;
for seg in meta.segments {
println!(
"{}: {:>4} {:>4}",
seg.id().uuid_string(),
seg.num_docs(),
seg.num_deleted_docs()
);
total_doc_count += seg.num_docs();
}
println!("\nTotal {} docs", total_doc_count);
他のマルチバイト文字 について
Tantivy では日本語の他のマルチバイト文字(中国語や韓国語)を使うためのTokenizerについてもREADMEで紹介されている。