Sonicは、 Elasticsearchなどフル機能の検索システムの代替として開発が進められている、オープンソースでスキーマレスの検索バックエンドだ。自然言語による検索クエリの正規化とオートコンプリート機能を備え、検索クエリに最も関連性の高い結果を返すことができる。Sonicはドキュメントインデックスに代えて識別子インデックスを実装しており、クエリに対して、外部データベースで解決可能なIDのリストを返す。Crispのエンジニアが設計したSonicは、同社のカスタマーサポートメッセージングサービス検索プロダクトで使用されている。
Sonicのインデックス付きデータは、バケットによって整理されたコレクションに保存される。Sonicは単一のバケットで実行することも、複数のバケットを使用するように設定することもできる。これにより、検索のユースケースに合わせてインデックスをカスタマイズすることが可能になっている。検索クエリは、外部データベースによる解決を前提としたオブジェクト識別子を返す。このような設計上の決定により、ディスクに保存されるデータが最小限に抑えられている。その他の追加機能としては、クエリの誤字修正や用語のオートコンプリート、 Unicodeによる80以上の言語のサポート、などがある。クエリとインデックスの生成はSonic Channelプロトコル経由で実行され、Node.js、PHP、Rust、Go、Pythonなどの言語ライブラリが提供されている。
Sonicの検索エンジンは、 逆索引(inverted index)で構成されている。インデックス付けされたセンテンスは単語に分割され、各単語がキー、センテンスがクエリの一致した時に返されるインデックス付き値オブジェクトとして、RocksDBを使用したキー/バリューデータベースに格納される。オブジェクトがインデックスに追加またはインデックスから削除されると、バックグラウンドジョブがインデックスを統合して、変更結果が検索に反映されるようにする。Sonicは、安全性を重視した最新のプログラミング言語であるRustで書かれている。Rustには、コンパイルされたバイナリを提供すると同時に、Sonicのリアルタイムメモリ管理のニーズを妨害するガベージコレクタを持たないというメリットがある。
Crispの共同設立者であるValerian Saliou氏によると、SonicはRedisの軽量でオープンソースのデザインにインスパイアされていることから、自らを"検索用のRedis"とうたっている。Redisのように軽量な実装を実現すため、Sonicの設計者たちは、機能を決定する上で次のような基準を採用した。
- この機能は本当に必要か?
- どうすれば簡単にできるのか?
- 高速性と軽量性は保てるか?
- 派手な新機能のために、設定が難しくなるようなことはないか?
この基準を満たすために、開発ではいくつかのトレードオフを行った。自然言語処理(NLP)システムはセンテンスのレベルではなく、単語レベルで機能する。従って、単語の予測は可能だが、センテンス内の次の単語の予測はできない。この決定により、入力ミスを修正するFSTグラフを浅く保つことができたため、処理時間とスペースの複雑性が軽減されると同時に、ストレージ要件を最小限に抑えることが可能になった。Sonicは、FSTの再構築サイクルをバッチ処理する。従って、検索インデックスの更新は完全にリアルタイムではなく、新しい用語は次のビルドサイクルまで表示されない可能性がある。さらに、Sonicとの対話用にサポートされているプロトコルはSonic Channelプロトコルのみで、HTTPAPIは使用できない。
Crispのヘルプデスクでは、Sonicを実際に試すことができる。インストールと管理の詳細については、 SonicのGithubページを参照してほしい。