<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Carly Richmond - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Carly Richmond - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/jp/search-labs/author/carly-richmond</link>
    </image>
    <link>https://www.elastic.co/jp/search-labs/author/carly-richmond</link>
    <atom:link href="https://www.elastic.co/jp/search-labs/rss/author/carly-richmond.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[jp]]></language>
    <lastBuildDate>Mon, 21 Sep 2026 17:01:29 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Elasticsearchで2つのインデックスを結合する方法]]></title>
    <description><![CDATA[Elasticsearch で 2 つのインデックスを結合するための用語クエリ、Logstash elasticsearch フィルター、エンリッチ プロセッサ、ES|QL の使用方法を説明します。]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch では、2 つのインデックスを結合することは、従来の SQL リレーショナル データベースほど簡単ではありません。ただし、Elasticsearch が提供する特定のテクニックと機能を使用すれば、同様の結果を得ることは可能です。</p><p>歴史的に、多くの人々は、異なるインデックスを結合するメカニズムとして<a href="https://www.elastic.co/jp/docs/reference/elasticsearch/mapping-reference/nested"><code>nested</code></a><a href="https://www.elastic.co/jp/docs/reference/elasticsearch/mapping-reference/nested">フィールド タイプ</a>を使用してきました。しかし、クエリのコストが高く、Kibana、特にLensの視覚化のサポートが不完全であるため、制限がありました。</p><p>この記事では、Elasticsearch で 2 つのインデックスを結合するプロセスを詳しく説明し、次のアプローチに焦点を当てます。 </p><ol><li><p><code>terms</code>クエリの使用</p></li><li><p>取り込みパイプラインで<code>enrich</code>プロセッサを使用する</p></li><li><p>Logstash <code>elasticsearch</code>フィルター プラグイン</p></li><li><p>ES|QL <code>ENRICH</code></p></li><li><p>ES|QL <code>LOOKUP JOIN</code></p></li></ol><h2>用語クエリの使用</h2><p><a href="https://www.elastic.co/jp/docs/reference/query-languages/query-dsl/query-dsl-terms-query">用語クエリは</a>、Elasticsearch で 2 つのインデックスを結合する最も効果的な方法の 1 つです。このクエリは、特定のフィールドに 1 つ以上の正確な用語を含むドキュメントを取得するために使用されます。ここでは、これを使用して 2 つのインデックスを結合する方法について説明します。</p><p>まず、最初のインデックスから必要なデータを取得する必要があります。これは、単純な GET リクエストを使用して<code>_source</code>属性から値を取得することで実行できます。</p># Simple GET request
GET first_index/_search<p>最初のインデックスからデータを取得したら、それを使用して 2 番目のインデックスをクエリできます。これは、一致させるフィールドと値を指定する<code>terms</code>クエリを使用して行われます。</p><p>次に例を示します。</p>GET second_index/_search
{
  "query": {
    "terms": {
      "field_in_second_index": ["value1_from_first_index", "value2_from_first_index"]
    }
  }
}<p>
この例では、 <code>field_in_second_index</code> 、最初のインデックスの値と一致させる 2 番目のインデックスのフィールドです。<code>value1_from_first_index</code>と<code>value2_from_first_index</code> 、2 番目のインデックスで一致させる最初のインデックスの値です。</p><p>用語クエリは<a href="https://www.elastic.co/jp/docs/reference/query-languages/query-dsl/query-dsl-terms-query#query-dsl-terms-lookup">、用語ルックアップ</a>と呼ばれる手法を使用して、上記の 2 つの手順を 1 回のショットで実行するためのサポートも提供します。Elasticsearch は、別のインデックスから一致する値を透過的に取得します。たとえば、プレーヤーのリストを含むチーム インデックスがある場合:</p>PUT teams/_doc/team1
{
  "players":   ["john", "bill", "michael"]
}
PUT teams/_doc/team2
{
  "players":   ["aaron", "joe", "donald"]
}<p>以下に示すように、team1 でプレイしているすべての人々の人インデックスをクエリすることができます。</p>GET people/_search?pretty
{
  "query": {
    "terms": {
        "name" : {
            "index" : "teams",
            "id" : "team1",
            "path" : "players"
        }
    }
  }
}<p>上記の例では、Elasticsearchはチームインデックス内のID team1 を持つドキュメントからプレーヤー名を透過的に取得します（つまり、たとえば、「john」、「bill」、「michael」など) を検索し、名前フィールドにこれらの値のいずれかを含む人物インデックス内のすべてのドキュメントを検索します。</p><p>興味がある方のために、同等の SQL クエリは次のようになります。</p><h2>エンリッチプロセッサの使用</h2><p><a href="https://www.elastic.co/jp/docs/reference/enrich-processor/enrich-processor"><code>enrich</code></a><a href="https://www.elastic.co/jp/docs/reference/enrich-processor/enrich-processor">プロセッサは</a>、Elasticsearch 内の 2 つのインデックスを結合するために使用できるもう 1 つの強力なツールです。このプロセッサは、事前に定義されたエンリッチ インデックスからデータを追加することで、受信ドキュメントのデータをエンリッチします。</p><p>エンリッチ プロセッサを使用して 2 つのインデックスを結合する方法は次のとおりです。</p><p>1. まず、エンリッチポリシーを作成する必要があります。このポリシーは、エンリッチメントに使用するインデックス、一致させるフィールド、および受信ドキュメントのエンリッチメントに使用するフィールドを定義します。</p><p>次に例を示します。</p>PUT _enrich/policy/my_enrich_policy
{
  "match": {
    "indices": "first_index",
    "match_field": "field_in_first_index",
    "enrich_fields": ["field_to_enrich"]
  }
}<p>2. ポリシーが作成されたら、それを実行して、新しく作成されたポリシーからエンリッチ インデックスを作成する必要があります。</p>PUT _enrich/policy/my_enrich_policy/_execute<p>これにより、エンリッチメント中に使用される新しい非表示のエンリッチメント インデックスが構築されます。ソース インデックスのサイズによっては、この操作に時間がかかる場合があります。次のステップに進む前に、エンリッチポリシーが完全に構築されていることを確認してください。</p><p>3. エンリッチポリシーを構築したら、取り込みパイプラインでエンリッチプロセッサを使用して、受信ドキュメントのデータをエンリッチできます。</p>PUT _ingest/pipeline/my_pipeline
{
  "processors": [
    {
      "enrich": {
        "policy_name": "my_enrich_policy",
        "field": "field_in_second_index",
        "target_field": "enriched_field"
      }
    }
  ]
}<p>この例では、 <code>field_in_second_index</code> 、最初のインデックスの<code>match_field</code>と一致する必要がある 2 番目のインデックスのフィールドです。<code>enriched_field</code> 、最初のインデックスの<code>enrich_fields</code>から拡張されたデータを格納する、2 番目のインデックスの新しいフィールドです。</p><p>このアプローチの欠点の 1 つは、 <code>first_index</code>のデータが変更された場合、エンリッチ ポリシーを再実行する必要があることです。エンリッチされたインデックスは、その構築元となったソース インデックスから自動的に更新または同期されることはありません。ただし、 <code>first_index</code>が比較的安定している場合は、このアプローチはうまく機能します。</p><h2>Logstash elasticsearch フィルター プラグイン</h2><p>Logstash を使用する場合、上記の<code>enrich</code>プロセッサに似た別のオプションとして、 <code>elasticsearch</code>フィルター プラグインを使用して、指定されたクエリに基づいてイベントに関連フィールドを追加する方法があります。Logstash パイプラインの構成は、 <code>my-pipeline.conf</code>などの<code>.conf</code>ファイルに保存されます。</p><p>パイプラインが<a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-inputs-elasticsearch"><code>elasticsearch</code></a><a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-inputs-elasticsearch">入力プラグイン</a>を使用して Elasticsearch からログを取得し、選択範囲を絞り込むクエリを実行しているとします。</p>input {
  # Read all documents from Elasticsearch matching the given query
  elasticsearch {
    hosts =&gt; "localhost"
    query =&gt; '{ "query": { "match": { "statuscode": 200 } }, "sort": [ "_doc" ] }'
  }
}<p>特定のインデックスからの情報を使用してこれらのメッセージを拡充したい場合は、 <code>filter</code>セクションの<a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-filters-elasticsearch"><code>elasticsearch</code></a><a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-filters-elasticsearch">フィルター プラグイン</a>を使用してログを拡充できます。</p>filter {
   elasticsearch {
      hosts =&gt; ["localhost"]
      index =&gt; "index_name"
      query =&gt; "type:start AND operation:%{[opid]}"
      fields =&gt; { "@timestamp" =&gt; "started" }
   }
}<p>上記のコードは、インデックス<code>index_name</code>から、 <code>type</code>が開始され、操作フィールドが指定された<code>opid</code>と一致するドキュメントを検索し、 <code>@timestamp</code>フィールドの値を<code>started</code>という名前の新しいフィールドにコピーします。</p><p>強化されたドキュメントは適切な出力ソース（この場合は<a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-outputs-elasticsearch"><code>elasticsearch</code></a><a href="https://www.elastic.co/jp/docs/reference/logstash/plugins/plugins-outputs-elasticsearch">出力プラグイン</a>を使用して Elasticsearch ）に送信されます。</p>output {
    elasticsearch {
        hosts =&gt; "localhost"
        data_stream =&gt; "true"
    }
}<p>すでに Logstash を使用している場合、このオプションは、エンリッチメント ロジックを 1 か所に統合し、新しいイベントが発生したときに処理するのに役立ちます。ただし、そうでない場合は、ソリューションが複雑になり、実行および保守する必要がある別のコンポーネントが追加されることになります。</p><h2>ES|QL エンリッチ</h2><p>バージョン 8.14 で GA となった<a href="https://www.elastic.co/jp/docs/explore-analyze/query-filter/languages/esql">ES|QL</a>は、Elasticsearch でサポートされるパイプ クエリ言語であり、データのフィルタリング、変換、分析を可能にします。ENRICH 処理コマンドを使用すると、エンリッチ ポリシーを使用して既存のインデックスからデータを追加できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbeb8992bde773461/6a17f6b663baff00c9741dd4/03aadddc08afffff3f6526c9c052999c97fa09dd-1600x989.png" alt="esql エンリッチ" /><p>元のエンリッチ プロセッサの例と同じポリシー<code>my_enrich_policy</code>を使用すると、ES|QL の例は次のようになります。</p><p>一致フィールドとエンリッチメント フィールド (この例ではそれぞれ<code>field_in_first_index</code>と<code>field_to_enrich</code>をオーバーライドすることもできます。</p><p>明らかな制限は、最初にエンリッチポリシーを指定する必要があることですが、ES|QL では、必要に応じてフィールドを微調整できる柔軟性が提供されます。</p><h2>ES|QL ルックアップ結合</h2><p>Elasticsearch 8.18 では、Elasticsearch でインデックスを結合する新しい方法、つまり<code>LOOKUP JOIN</code>コマンドが導入されました。このコマンドは、結合の右側にある新しい<a href="https://www.elastic.co/jp/docs/reference/elasticsearch/index-settings/index-modules#index-mode-setting">ルックアップ インデックス モード</a>を使用して、SQL スタイルの LEFT OUTER JOIN として動作します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt783ffb3f9802f92d/6a17f6b8e9ea870608a9c788/1d73495979c4d6bb675c4c966ea86d9a72dc1c48-510x605.png" alt="ES|QL ルックアップ結合" /><p>前の例をもう一度見てみると、新しいクエリは次のようになります。ここで、 <code>match_field</code> <code>first_index</code>と<code>second_index</code>両方に存在する必要があります。</p><p>LOOKUP JOIN が他のアプローチよりも優れている点は、 <code>enrich</code>ポリシーが不要であり、したがってポリシーの設定に関連する追加の処理も必要ないことです。これは、この記事で説明した他のアプローチとは異なり、頻繁に変更されるエンリッチメント データを扱う場合に役立ちます。</p><h2>まとめ</h2><p>結論として、Elasticsearch は従来の結合操作をサポートしていませんが、同様の結果を実現するために使用できるさまざまな機能を提供しています。具体的には、以下を使用して結合操作を実現する方法について説明しました。</p><ol><li><p><code>terms</code>クエリ</p></li><li><p>取り込みパイプラインの<code>enrich</code>プロセッサ</p></li><li><p>Logstash <code>elasticsearch</code>フィルター プラグイン</p></li><li><p>ES|QL <code>ENRICH</code></p></li><li><p>ES|QL <code>LOOKUP JOIN</code></p></li></ol><p>これらの方法には限界があり、特定の要件とデータの性質に基づいて慎重に使用する必要があることに注意することが重要です。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-join-two-indexes</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-join-two-indexes</guid>
    <category><![CDATA[基本]]></category>
    <dc:creator><![CDATA[Carly Richmond]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt74822b3b7cb2a41a/6a17f6b97f6f156288c09cc7/0d4736d10fa3e12e6233cd59993299c7bd48911b-680x450.png" length="0" type="image/png"/>
    <pubDate>Wed, 07 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[ElasticsearchとGoを使用して、ホリネズミ狩りをハイブリッド検索]]></title>
    <description><![CDATA[Elasticsearch と Elasticsearch Go クライアントを使用してキーワード検索とベクター検索を組み合わせることでハイブリッド検索を実現する方法を学びます。]]></description>
    <content:encoded><![CDATA[<p>このシリーズの前回の記事では、Elasticsearch Go クライアントを<a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">従来のキーワード検索</a>と<a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">ベクター検索</a>に使用する方法を説明しました。この第 3 部では、ハイブリッド検索について説明します。<a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> と<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html"> Elasticsearch</a> Go クライアント を使用して、ベクトル検索とキーワード検索の両方を組み合わせる方法の<a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch"> 例を</a> 紹介します。</p><h2>要件</h2><p>このシリーズのパート 1 と同様に、この例では次の前提条件が必要です。</p><ol><li><p>Goバージョン1.21以降のインストール</p></li><li><p><a href="https://go.dev/doc/code">Go ドキュメント</a>に記載されている推奨構造とパッケージ管理を使用して、独自の Go リポジトリを作成します。</p></li><li><p>独自の Elasticsearch クラスターを作成し、Wikipedia<a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources"> のフレンドリーな</a><a href="https://en.wikipedia.org/wiki/Gopher"> Gopher</a> を含む、 げっ歯類ベースのページ セットを設定します。</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia Gopherページ" /><h2>Elasticsearchへの接続</h2><p>繰り返しになりますが、私たちの例では、Go クライアントが提供する<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a>を使用します。クエリに対して安全な接続を確立するには、次のいずれかを使用してクライアントを構成する必要があります。</p><ol><li><p>Elastic Cloud を利用する場合の Cloud ID と API キー</p></li><li><p>クラスターURL、ユーザー名、パスワード、証明書</p></li></ol><p>Elastic Cloud にあるクラスターに接続すると、次のようになります。</p>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:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

	if err != nil {
		return nil, fmt.Errorf("unable to connect: %w", err)
	}

	return es, nil
}
<p>後続のセクションで示すように、 <code>client</code>接続は検索に使用できます。</p><h2>ハイブリッド検索の手動ブースティング</h2><p>検索アルゴリズムのセットを組み合わせる場合、従来のアプローチでは、各クエリ タイプを強化するために定数を手動で構成していました。具体的には、クエリごとに係数が指定され、結合された結果セットが予想されるセットと比較され、クエリのリコールが決定されます。次に、いくつかの要因セットを繰り返し、希望する状態に最も近いものを選択します。</p><p>たとえば、 <code>0.8</code>倍の係数でブーストされた単一のテキスト検索クエリと、 <code>0.2</code>倍の係数が低い knn クエリを組み合わせるには、次の例に示すように、両方のクエリ タイプで<code>Boost</code>フィールドを指定します。</p>func HybridSearchWithBoost(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	var k = 10
	var numCandidates = 10
	var knnBoost float32 = 0.2
	var queryBoost float32 = 0.8

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnSearch{
			Field:         "text_embedding.predicted_value",
			Boost:         &amp;knnBoost,
			K:             &amp;k,
			NumCandidates: &amp;numCandidates,
			QueryVectorBuilder: &amp;types.QueryVectorBuilder{
				TextEmbedding: &amp;types.TextEmbedding{
					ModelId:   "sentence-transformers__msmarco-minilm-l-12-v3",
					ModelText: term,
				},
			}}).
		Query(&amp;types.Query{
			Match: map[string]types.MatchQuery{
				"title": {
					Query: term,
					Boost: &amp;queryBoost,
				},
			},
		}).
		Do(context.Background())

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<p>各クエリの<code>Boost</code>オプションで指定された係数がドキュメント スコアに追加されます。一致クエリのスコアを knn クエリよりも大きな係数で増加させることにより、キーワード クエリの結果の重み付けがより大きくなります。</p><p>手動によるブースティングの課題は、特に検索の専門家でない場合、望ましい結果セットにつながる要因を見つけ出すために調整が必要になることです。ランダムな値を試してみて、希望する結果セットに近づくかどうかを調べるだけです。</p><h2>ハイブリッド検索とGoクライアントにおける相互ランク融合</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">Reciprocal Rank Fusion</a> (RRF) は、Elasticsearch 8.9 のハイブリッド検索のテクニカル プレビューとしてリリースされました。チューニングに関連する学習曲線を短縮し、結果セットを最適化するための要素の実験にかかる時間を短縮することを目的としています。</p><p>RRF では、以下のアルゴリズムでスコアをブレンドしてドキュメント スコアが再計算されます。</p>score := 0.0
// q is a query in the set of queries (vector and keyword search)
for _, q := range queries {
    // result(q) is the results 
    if document in result(q) {
        // k is a ranking constant (default 60)
        // rank(result(q), d) is the document's rank within result(q) 
        // range from 1 to the window_size (default 100)
        score +=  1.0 / (k + rank(result(q), d))
    }
}

return score
<p>RRF を使用する利点は、Elasticsearch 内で適切なデフォルト値を利用できることです。ランキング定数<code>k</code>デフォルトは<code>60</code>です。大規模なデータ セットを検索するときに、返されるドキュメントの関連性とクエリ パフォーマンスの間のトレードオフを提供するために、検討される各クエリの結果セットのサイズは<code>window_size</code>の値に制限されます。この値は、<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html#rrf-api">ドキュメント</a>で説明されているように、デフォルトで<code>100</code>になります。</p><p><code>k</code> また、 <code>windows_size</code> 、以下の例のように、Go クライアントの<code>Rank</code>メソッド内の<code>Rrf</code>構成内で構成することもできます。</p>func HybridSearchWithRRF(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	var k = 10
	var numCandidates = 10

	// Minimum required window size for the default result size of 10
	var windowSize int64 = 10
	var rankConstant int64 = 42

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnSearch{
			Field:         "text_embedding.predicted_value",
			K:             &amp;k,
			NumCandidates: &amp;numCandidates,
			QueryVectorBuilder: &amp;types.QueryVectorBuilder{
				TextEmbedding: &amp;types.TextEmbedding{
					ModelId:   "sentence-transformers__msmarco-minilm-l-12-v3",
					ModelText: term,
				},
			}}).
		Query(&amp;types.Query{
			Match: map[string]types.MatchQuery{
				"title": {Query: term},
			},
		}).
		Rank(&amp;types.RankContainer{
			Rrf: &amp;types.RrfRank{
				WindowSize:   &amp;windowSize,
				RankConstant: &amp;rankConstant,
			},
		}).
		Do(context.Background())

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<h2>まとめ</h2><p>ここでは、 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go クライアント</a>を使用して Elasticsearch でベクトル検索とキーワード検索を組み合わせる方法について説明しました。</p><p>このシリーズのすべてのコードについては、 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub リポジトリ</a>をご覧ください。まだご覧になっていない方は、このシリーズのすべてのコードについては<a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">パート 1</a>と<a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">パート 2</a>をご覧ください。</p><p><em>楽しいホリネズミ狩りを！</em></p><h2>各種資料</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearchガイド</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Goクライアント</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">ベクトル検索とは何ですか?| 弾性</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">相互ランク融合</a></p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client</guid>
    <category><![CDATA[Vector Database]]></category>
    <category><![CDATA[Go]]></category>
    <dc:creator><![CDATA[Carly Richmond,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcae959696d55a9b/6a1704d5ab7f085a56db9d7c/491ef9efbb30b253e1d9e3b7f816a9a23c8f5264-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 02 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch Goクライアントを使用してElasticsearchでベクトル検索を実行する]]></title>
    <description><![CDATA[実際の例を通して、Elasticsearch Go クライアントを使用して Elasticsearch でベクトル検索を実行する方法を学びます。]]></description>
    <content:encoded><![CDATA[<p>Go を含むあらゆるプログラミング言語でソフトウェアを構築することは、生涯にわたる学習に取り組むことです。Carly は大学時代や仕事を通じて、ベクトル検索の最新かつ最高の実装を含む、数多くのプログラミング言語やテクノロジーに携わってきました。しかし、それだけでは十分ではありませんでした!それで最近カーリーも囲碁を始めました。</p><p>動物、プログラミング言語、そして親しみやすい著者と同じように、検索もさまざまな方法の進化を遂げており、独自の検索ユースケースに応じてどれを選択するかを決めるのは難しい場合があります。このブログでは、ベクトル検索の概要と、<a href="https://www.elastic.co/elasticsearch/"> Elasticsearch</a> および<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html"> Elasticsearch Go</a> クライアント を使用した各アプローチの<a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch"> 例を</a> 紹介します。これらの例では、Elasticsearch と Go のベクトル検索を使用して、ホリネズミを見つけて、その食べ物を特定する方法を説明します。</p><h2>要件</h2><p>この例を実行するには、次の前提条件が満たされていることを確認してください。</p><ol><li><p>Goバージョン1.21以降のインストール</p></li><li><p>独自のGoリポジトリを作成する</p></li><li><p>独自の Elasticsearch クラスターを作成し、Wikipedia のフレンドリーな<a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>を含む一連のげっ歯類ベースのページを設定します。</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia Gopherページ" /><h2>Elasticsearchへの接続</h2><p>この例では、Go クライアントが提供する<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a>を利用します。クエリに対して安全な接続を確立するには、次のいずれかを使用してクライアントを構成する必要があります。</p><ol><li><p>Elastic Cloud を利用する場合のクラウド ID と API キー。</p></li><li><p>クラスター URL、ユーザー名、パスワード、証明書。</p></li></ol><p>Elastic Cloud にあるクラスターに接続すると、次のようになります。</p>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:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

	if err != nil {
		return nil, fmt.Errorf("unable to connect: %w", err)
	}

	return es, nil
}
<p>後続のセクションに示すように、 <code>client</code>接続はベクトル検索に使用できます。</p><h2>ベクトル検索</h2><p>ベクトル検索は、検索問題をベクトルを使用した数学的な比較に変換することでこの問題を解決しようとします。ドキュメント埋め込みプロセスには、モデルを使用してドキュメントを高密度ベクトル表現、つまり単純な数値のストリームに変換する追加の段階があります。このアプローチの利点は、画像や音声などのテキスト以外のドキュメントをクエリと一緒にベクトルに変換して検索できることです。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4b3b9b2ad1e8f46/6a1704d06234e0800fdb1927/b113358093e367358d684f7aaf0a6684ebb2d0dd-1440x653.png" alt="ベクトル探索図" /><p>簡単に言えば、ベクトル検索はベクトル距離の計算のセットです。下の図では、クエリ<code>Go Gopher</code>のベクトル表現がベクトル空間内のドキュメントと比較され、最も近い結果 (定数<code>k</code>で示される) が返されます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c736ecfc49bb038/6a1704d2cf4f25bcb6b2d075/54a17a4b41029644e7c66f33d428e8d01a6f4ce3-1184x743.png" alt="Gopherベクトル空間の例" /><p>ドキュメントの埋め込みを生成するために使用するアプローチに応じて、ホリネズミが何を食べるかを調べる方法が 2 つあります。</p><h3>アプローチ1: 独自のモデルを持ち込む</h3><p>Platinum ライセンスでは、モデルをアップロードし、推論 API を使用して Elasticsearch 内で埋め込みを生成できます。モデルの設定には 6 つのステップがあります。</p><ol><li><p>モデル リポジトリからアップロードする PyTorch モデルを選択します。この例では、Hugging Face の<a href="https://huggingface.co/sentence-transformers/msmarco-MiniLM-L-12-v3">sentence-transformers/msmarco-MiniLM-L-12-v3</a>を使用して埋め込みを生成します。</p></li><li><p>Elasticsearch クラスターとタスク タイプ<code>text_embeddings</code>の資格情報を使用して<a href="https://www.elastic.co/guide/en/elasticsearch/client/eland/current/overview.html">、Python 用の Eland Machine Learning クライアント</a>でモデルを Elastic にロードします。Eland がインストールされていない場合は、以下に示すように<a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-import-model.html#ml-nlp-import-docker">Docker を使用してインポート手順を実行</a>できます。</p></li></ol>docker run -it --rm --network host \
    docker.elastic.co/eland/eland \
    eland_import_hub_model \
      --cloud-id $ELASTIC_CLOUD_ID \
      --es-api-key $ELASTIC_API_KEY \
      --hub-model-id sentence-transformers/msmarco-MiniLM-L-12-v3 \
      --task-type text_embedding
<ol><li><p>アップロードしたら、サンプル ドキュメントを使用してモデル<code>sentence-transformers__msmarco-minilm-l-12-v3</code>をすぐにテストし、埋め込みが期待どおりに生成されることを確認します。</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a399e1f50ecfdaf/6a1704d4ab7f08935edb9d78/fbbdde621361a487eb07304bed029c228d0f7aa6-1440x789.png" alt="Elastic Test トレーニング済みモデルの例" /><ol><li><p>推論プロセッサを含む取り込みパイプラインを作成します。これにより、アップロードされたモデルを使用してベクター表現を生成できるようになります。</p></li></ol>PUT _ingest/pipeline/search-rodents-vector-embedding-pipeline
{
  "processors": [
    {
      "inference": {
        "model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
        "target_field": "text_embedding",
        "field_map": {
          "body_content": "text_field"
        }
      }
    }
  ]
}
<ol><li><p>各ドキュメントに対して生成されたベクトル埋め込みを格納するための、タイプ<code>dense_vector</code>のフィールド<code>text_embedding.predicted_value</code>を含む新しいインデックスを作成します。</p></li></ol>PUT vector-search-rodents
{
  "mappings": {
    "properties": {
      "text_embedding.predicted_value": {
        "type": "dense_vector",
        "dims": 384,
        "index": true,
        "similarity": "cosine"
      },
      "text": {
        "type": "text"
      }
    }
  }
}
<ol><li><p>新しく作成された取り込みパイプラインを使用してドキュメントのインデックスを再作成し、各ドキュメントの追加フィールド<code>text_embedding.predicted_value</code>としてテキスト埋め込みを生成します。</p></li></ol>POST _reindex
{
  "source": {
    "index": "search-rodents"
  },
  "dest": {
    "index": "vector-search-rodents",
    "pipeline": "search-rodents-vector-embedding-pipeline"
  }
}
<p>次の例に示すように、新しいインデックス<code>vector-search-rodents</code>を使用して、同じ検索 API で<code>Knn</code>オプションを使用できるようになりました。</p>func VectorSearch(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
  var k = 10
	var numCandidates = 10

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnSearch{
      # Field in document containing vector
			Field:         "text_embedding.predicted_value",
      # Number of neighbors to return
			K:             &amp;k,
      # Number of candidates to evaluate in comparison
			NumCandidates: &amp;numCandidates,
      # Generate query vector using the same model used in the inference processor
			QueryVectorBuilder: &amp;types.QueryVectorBuilder{
				TextEmbedding: &amp;types.TextEmbedding{
					ModelId:   "sentence-transformers__msmarco-minilm-l-12-v3",
					ModelText: term,
				},
			}}).Do(context.Background())

	if err != nil {
		return nil, fmt.Errorf("error in rodents vector search: %w", err)
	}

	return getRodents(res.Hits.Hits)
}
<p>アンマーシャリングによる JSON 結果オブジェクトの変換は、キーワード検索の例とまったく同じ方法で実行されます。定数<code>K</code>と<code>NumCandidates</code>使用すると、返される隣接ドキュメントの数と、シャードごとに考慮する候補の数を設定できます。候補の数を増やすと結果の精度は上がりますが、比較が多く実行されるためクエリの実行時間が長くなることに注意してください。</p><p>クエリ<code>What do Gophers eat?</code>を使用してコードを実行すると、返される結果は以下と同様になり、以前のキーワード検索とは異なり、Gopher の記事に要求された情報が含まれていることが強調表示されます。</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher} 
  {ID:64f74ed34acb3d71aed91fcd Title:Squirrel - Wikipedia Url:https://en.wikipedia.org/wiki/Squirrel} 
  //Other results omitted
]
<h3>アプローチ2：ハグフェイス推論API</h3><p>もう 1 つのオプションは、Elasticsearch の外部で同じ埋め込みを生成し、ドキュメントの一部として取り込むことです。このオプションは Elasticsearch 機械学習ノードを使用しないため、無料利用枠で実行できます。</p><p>Hugging Face は、無料で使用できるレート制限付きの<a href="https://huggingface.co/docs/api-inference/index">推論 API を</a>公開しています。アカウントと API トークンを使用すると、実験やプロトタイピングを開始するために同じ埋め込みを手動で生成できます。実稼働環境での使用は推奨されません。同様のアプローチを使用して、ローカルで独自のモデルを呼び出して埋め込みを生成したり、有料の API を使用したりすることもできます。</p><p>以下の関数<code>GetTextEmbeddingForQuery</code>では、クエリ文字列に対して推論 API を使用して、エンドポイントへの<code>POST</code>リクエストから返されるベクトルを生成します。</p>// HuggingFace text embedding helper
func GetTextEmbeddingForQuery(term string) []float32 {
    // HTTP endpoint
    model := "sentence-transformers/msmarco-minilm-l-12-v3"
    posturl := fmt.Sprintf("https://api-inference.huggingface.co/pipeline/feature-extraction/%s", model)

    // JSON body
    body := []byte(fmt.Sprintf(`{
        "inputs": "%s",
        "options": {"wait_for_model":True}
    }`, term))

    // Create a HTTP post request
    r, err := http.NewRequest("POST", posturl, bytes.NewBuffer(body))

    if err != nil {
        log.Fatal(err)
        return nil
    }

    token := os.Getenv("HUGGING_FACE_TOKEN")
    r.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))

    client := &amp;http.Client{}
    res, err := client.Do(r)
    if err != nil {
        panic(err)
    }

    defer res.Body.Close()

    var post []float32
    derr := json.NewDecoder(res.Body).Decode(&amp;post)

    if derr != nil {
        log.Fatal(derr)
        return nil
    }

    return post
}
<p>結果の<code>[]float32</code>型のベクトルは、 <code>QueryVectorBuilder</code>オプションを使用する代わりに<code>QueryVector</code>として渡され、以前に Elastic にアップロードされたモデルが活用されます。</p>func VectorSearchWithGeneratedQueryVector(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	vector, err := GetTextEmbeddingForQuery(term)
	if err != nil {
		return nil, err
	}

	if vector == nil {
		return nil, fmt.Errorf("unable to generate vector: %w", err)
	}

  var k = 10
	var numCandidates = 10

	res, err := client.Search().
		Index("vector-search-rodents").
		Knn(types.KnnSearch{
      # Field in document containing vector
			Field:         "text_embedding.predicted_value",
      # Number of neighbors to return
			K:             &amp;k,
      # Number of candidates to evaluate in comparison
			NumCandidates: &amp;numCandidates,
      # Query vector returned from Hugging Face inference API
			QueryVector:   vector,
		}).
		Do(context.Background())

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<p><code>K</code>と<code>NumCandidates</code>オプションは2つのオプションに関係なく同じままであり、埋め込みを生成するために同じモデルを使用しているため、同じ結果が生成されることに注意してください。</p><h2>まとめ</h2><p>ここでは、 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go クライアント</a>を使用して Elasticsearch でベクトル検索を実行する方法について説明しました。このシリーズのすべてのコードについては、 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub リポジトリ</a>をご覧ください。<a href="https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client">パート 3</a>に進み、<a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">パート 1</a>で説明した Go のキーワード検索機能とベクトル検索を組み合わせる方法の概要を確認します。</p><p>それまでは、楽しいホリネズミ狩りを！</p><h2>各種資料</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearchガイド</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Goクライアント</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">ベクトル検索とは何ですか?| 弾性</a></p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client</guid>
    <category><![CDATA[Vector Database]]></category>
    <category><![CDATA[Go]]></category>
    <dc:creator><![CDATA[Carly Richmond,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcae959696d55a9b/6a1704d5ab7f085a56db9d7c/491ef9efbb30b253e1d9e3b7f816a9a23c8f5264-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch Go クライアントでテキストクエリを実行する]]></title>
    <description><![CDATA[実際の例を通して、Elasticsearch Go クライアントを使用して Elasticsearch で従来のテキスト クエリを実行する方法を学びます。]]></description>
    <content:encoded><![CDATA[<p>Go を含むあらゆるプログラミング言語でソフトウェアを構築することは、生涯にわたる学習に取り組むことです。大学時代および仕事のキャリアを通じて、Carly は多言語話者になることに適応し、Python、C、JavaScript、TypeScript、Java など、多くのプログラミング言語に触れる必要がありました。しかし、それだけでは十分ではありませんでした!それで最近彼女も囲碁を始めました！</p><p>動物、プログラミング言語、そして親切な著者の一人と同じように、検索もさまざまな方法の進化を遂げており、独自の検索ユースケースに応じてどれを選択するかを決めるのは難しい場合があります。このブログでは、従来のキーワード検索の概要と、<a href="https://www.elastic.co/elasticsearch/"> Elasticsearch</a> と<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html"> Elasticsearch</a> Go<a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch"> クライアント を使用した 例を</a> 紹介します。</p><h2>要件</h2><p>この例を実行するには、次の前提条件が満たされていることを確認してください。</p><ol><li><p>Goバージョン1.21以降のインストール</p></li><li><p><a href="https://go.dev/doc/code">Go ドキュメント</a>に記載されている推奨構造とパッケージ管理を使用して、独自の Go リポジトリを作成します。</p></li><li><p>独自の Elasticsearch クラスターを作成し、Wikipedia<a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources"> のフレンドリーな</a> <a href="https://en.wikipedia.org/wiki/Gopher">Gopher を含む一連の げっ歯類ベースのページ を設定します。</a></p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia Gopherページ" /><h2>Elasticsearchへの接続</h2><p>この例では、Go クライアントが提供する<a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a>を使用します。クエリに対して安全な接続を確立するには、次のいずれかを使用してクライアントを構成する必要があります。</p><ol><li><p>Elastic Cloud を利用する場合のクラウド ID と API キー。</p></li><li><p>クラスター URL、ユーザー名、パスワード、証明書。</p></li></ol><p>Elastic Cloud にあるクラスターに接続すると、次のようになります。</p>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:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

	if err != nil {
		return nil, fmt.Errorf("unable to connect: %w", err)
	}

	return es, nil
}
<p>後ほど示すように、 <code>client</code>接続は検索に使用できます。</p><h2>キーワード検索</h2><p>キーワード検索は、1990 年に初めて文書化されたインターネット検索エンジンである<a href="https://en.wikipedia.org/wiki/Archie_(search_engine)">Archie</a>の誕生以来、私たちがよく知っている基本的な検索タイプです。</p><p>キーワード検索の中心的な要素は、ドキュメントを転置インデックスに変換することです。教科書の巻末にある索引とまったく同じように、転置索引にはトークンのリストと各文書内でのその位置とのマッピングが含まれています。以下の図は、インデックス生成の主要な段階を示しています。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt366681a12027f14b/6a17e7aa1d1b831c2093e452/9cd7b2a60d9aa54facb37738b821bba6ca925830-1440x581.png" alt="転置インデックス生成" /><p>上記のように、Elasticsearch でのトークンの生成は、次の 3 つの主要な段階で構成されます。</p><ol><li><p>0 個以上の<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html"><code>char_filters</code></a>を使用して不要な文字を削除します。この例では、 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html"><code>html_strip</code></a>フィルターを使用して<code>body_content</code>フィールド内の HTML 要素を削除しています。</p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html"><code>standard</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html">トークナイザー</a>を使用してコンテンツからトークンを分割します。スペースとキーの句読点によって分割されます。</p></li><li><p>不要なトークンを削除したり、 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html"><code>lowercase</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html">トークン フィルター</a>などの 0 個以上の<code>filter</code>オプションや、 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html"><code>snowball</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html">ステマー</a>などのステマーを使用してトークンを言語ルートに戻すことで、トークナイザーの出力ストリームからトークンを変換します。</p></li></ol><h2>Go で Elasticsearch を検索する</h2><p>Go クライアントでクエリを実行するときは、以下の例のように、検索するインデックスを指定し、クエリとその他のオプションを渡します。</p>func KeywordSearch(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	res, err := client.Search().
		Index("search-rodents").
		Query(&amp;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)
}
<p>上記の例では、標準の<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"><code>match</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html">クエリ</a>を実行して、関数に渡された特定の文字列を含むインデックス内のドキュメントを検索します。<code>Do(context.Background())</code>を介して<a href="https://pkg.go.dev/context#Background">新しい空のコンテキストを</a>検索実行に渡すことに注意してください。さらに、Elasticsearch によって返されたエラーは、ログ記録とエラー処理のために<code>err</code>属性に出力されます。</p><p>結果は、ドキュメント自体を JSON 形式で含む<code>_Source</code>属性とともに<code>res.Hits.Hits</code>に返されます。このソースを Go 対応の構造体に変換するには、次の例に示すように、Go encoding/json<a href="https://pkg.go.dev/encoding/json"> パッケージを</a> 使用して JSON 応答を<a href="https://pkg.go.dev/encoding/json#Unmarshal"> アンマーシャリングする</a> 必要があります。</p>func getRodents(hits []types.Hit) ([]Rodent, error) {
	var rodents []Rodent

	for _, hit := range hits {
		var currentRodent Rodent
		err := json.Unmarshal(hit.Source_, &amp;currentRodent)

		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
}
<p>クエリ<code>gopher</code>を検索してアンマーシャリングすると、期待どおりに Gopher の Wikipedia ページが返されます。</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher}
]
<p>しかし、 <code>What do Gophers eat?</code>に問い合わせても、期待する結果は得られません。</p>[]
<p>シンプルなキーワード検索により、私たちが普段使用しているアプリケーションと同じように、Go アプリケーションに高いパフォーマンスで結果を返すことができます。また、特定の会社や用語を検索するなどのシナリオに関連する用語の完全一致にも最適です。</p><p>しかし、上で見たように、語彙の不一致の問題により、文脈と意味を識別するのが困難です。さらに、画像や音声などのテキスト以外のファイル形式のサポートも困難です。</p><h2>まとめ</h2><p>ここでは、 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go クライアント</a>を使用して Elasticsearch で従来のテキスト クエリを実行する方法について説明しました。Go はインフラストラクチャのスクリプトや Web サーバーの構築に広く使用されているため、Go で検索する方法を知っておくと便利です。</p><p>このシリーズのすべてのコードについては、 <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">GitHub リポジトリ</a>をご覧ください。<a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">パート 2</a>に進み、ベクトル検索の概要と、Go でベクトル検索を実行する方法について説明します。それまでは、楽しいホリネズミ狩りを！</p><h2>各種資料</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearchガイド</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Goクライアント</a></p></li><li><p><a href="https://codingexplained.com/coding/elasticsearch/understanding-analysis-in-elasticsearch-analyzers">Elasticsearch の分析（アナライザー）を理解する by Bo Andersen | #CodingExplained</a></p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client</guid>
    <category><![CDATA[Go]]></category>
    <dc:creator><![CDATA[Carly Richmond,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcae959696d55a9b/6a1704d5ab7f085a56db9d7c/491ef9efbb30b253e1d9e3b7f816a9a23c8f5264-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 31 Oct 2023 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>