Elasticsearch Go クライアントでテキストクエリを実行する
実際の例を通して、Elasticsearch Go クライアントを使用して Elasticsearch で従来のテキスト クエリを実行する方法を学びます。
Go を含むあらゆるプログラミング言語でソフトウェアを構築することは、生涯にわたる学習に取り組むことです。大学時代および仕事のキャリアを通じて、Carly は多言語話者になることに適応し、Python、C、JavaScript、TypeScript、Java など、多くのプログラミング言語に触れる必要がありました。しかし、それだけでは十分ではありませんでした!それで最近彼女も囲碁を始めました!
動物、プログラミング言語、そして親切な著者の一人と同じように、検索もさまざまな方法の進化を遂げており、独自の検索ユースケースに応じてどれを選択するかを決めるのは難しい場合があります。このブログでは、従来のキーワード検索の概要と、 Elasticsearch と Elasticsearch Go クライアント を使用した 例を 紹介します。
要件
この例を実行するには、次の前提条件が満たされていることを確認してください。
Goバージョン1.21以降のインストール
Go ドキュメントに記載されている推奨構造とパッケージ管理を使用して、独自の Go リポジトリを作成します。
独自の Elasticsearch クラスターを作成し、Wikipedia のフレンドリーな Gopher を含む一連の げっ歯類ベースのページ を設定します。

Elasticsearchへの接続
この例では、Go クライアントが提供するTyped APIを使用します。クエリに対して安全な接続を確立するには、次のいずれかを使用してクライアントを構成する必要があります。
Elastic Cloud を利用する場合のクラウド ID と API キー。
クラスター URL、ユーザー名、パスワード、証明書。
Elastic Cloud にあるクラスターに接続すると、次のようになります。
func GetElasticsearchClient() (*elasticsearch.TypedClient, error) {
var cloudID = os.Getenv("ELASTIC_CLOUD_ID")
var apiKey = os.Getenv("ELASTIC_API_KEY")
var es, err = elasticsearch.NewTypedClient(elasticsearch.Config{
CloudID: cloudID,
APIKey: apiKey,
Logger: &elastictransport.ColorLogger{os.Stdout, true, true},
})
if err != nil {
return nil, fmt.Errorf("unable to connect: %w", err)
}
return es, nil
}後ほど示すように、 client接続は検索に使用できます。
キーワード検索
キーワード検索は、1990 年に初めて文書化されたインターネット検索エンジンであるArchieの誕生以来、私たちがよく知っている基本的な検索タイプです。
キーワード検索の中心的な要素は、ドキュメントを転置インデックスに変換することです。教科書の巻末にある索引とまったく同じように、転置索引にはトークンのリストと各文書内でのその位置とのマッピングが含まれています。以下の図は、インデックス生成の主要な段階を示しています。

上記のように、Elasticsearch でのトークンの生成は、次の 3 つの主要な段階で構成されます。
0 個以上の
char_filtersを使用して不要な文字を削除します。この例では、html_stripフィルターを使用してbody_contentフィールド内の HTML 要素を削除しています。standardトークナイザーを使用してコンテンツからトークンを分割します。スペースとキーの句読点によって分割されます。不要なトークンを削除したり、
lowercaseトークン フィルターなどの 0 個以上のfilterオプションや、snowballステマーなどのステマーを使用してトークンを言語ルートに戻すことで、トークナイザーの出力ストリームからトークンを変換します。
Go で Elasticsearch を検索する
Go クライアントでクエリを実行するときは、以下の例のように、検索するインデックスを指定し、クエリとその他のオプションを渡します。
func KeywordSearch(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
res, err := client.Search().
Index("search-rodents").
Query(&types.Query{
Match: map[string]types.MatchQuery{
"title": {Query: term},
},
}).
From(0).
Size(10).
Do(context.Background())
if err != nil {
return nil, fmt.Errorf("could not search for rodents: %w", err)
}
return getRodents(res.Hits.Hits)
}上記の例では、標準のmatchクエリを実行して、関数に渡された特定の文字列を含むインデックス内のドキュメントを検索します。Do(context.Background())を介して新しい空のコンテキストを検索実行に渡すことに注意してください。さらに、Elasticsearch によって返されたエラーは、ログ記録とエラー処理のためにerr属性に出力されます。
結果は、ドキュメント自体を JSON 形式で含む_Source属性とともにres.Hits.Hitsに返されます。このソースを Go 対応の構造体に変換するには、次の例に示すように、Go encoding/json パッケージを 使用して JSON 応答を アンマーシャリングする 必要があります。
func getRodents(hits []types.Hit) ([]Rodent, error) {
var rodents []Rodent
for _, hit := range hits {
var currentRodent Rodent
err := json.Unmarshal(hit.Source_, ¤tRodent)
if err != nil {
return nil, fmt.Errorf("an error occurred while unmarshaling rodent %s: %w", hit.Id_, err)
}
currentRodent.ID = hit.Id_
rodents = append(rodents, currentRodent)
}
return rodents, nil
}クエリgopherを検索してアンマーシャリングすると、期待どおりに Gopher の Wikipedia ページが返されます。
[
{ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher}
]しかし、 What do Gophers eat?に問い合わせても、期待する結果は得られません。
[]シンプルなキーワード検索により、私たちが普段使用しているアプリケーションと同じように、Go アプリケーションに高いパフォーマンスで結果を返すことができます。また、特定の会社や用語を検索するなどのシナリオに関連する用語の完全一致にも最適です。
しかし、上で見たように、語彙の不一致の問題により、文脈と意味を識別するのが困難です。さらに、画像や音声などのテキスト以外のファイル形式のサポートも困難です。
まとめ
ここでは、 Elasticsearch Go クライアントを使用して Elasticsearch で従来のテキスト クエリを実行する方法について説明しました。Go はインフラストラクチャのスクリプトや Web サーバーの構築に広く使用されているため、Go で検索する方法を知っておくと便利です。
このシリーズのすべてのコードについては、 GitHub リポジトリをご覧ください。パート 2に進み、ベクトル検索の概要と、Go でベクトル検索を実行する方法について説明します。それまでは、楽しいホリネズミ狩りを!
