<?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/de/search-labs/author/carly-richmond</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/carly-richmond</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/carly-richmond.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 05:13:49 GMT</lastBuildDate>
  <item>
    <title><![CDATA[So verbinden Sie zwei Indizes in Elasticsearch]]></title>
    <description><![CDATA[Erläuterung der Verwendung der Begriffe Abfrage, Logstash Elasticsearch-Filter, Anreicherungsprozessor und ES|QL zum Verbinden zweier Indizes in Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>In Elasticsearch ist das Verbinden zweier Indizes nicht so einfach wie in herkömmlichen relationalen SQL-Datenbanken. Mit bestimmten Techniken und Funktionen von Elasticsearch können jedoch ähnliche Ergebnisse erzielt werden.</p><p>In der Vergangenheit haben viele Leute den<a href="https://www.elastic.co/de/docs/reference/elasticsearch/mapping-reference/nested"> Feldtyp</a> <a href="https://www.elastic.co/de/docs/reference/elasticsearch/mapping-reference/nested"><code>nested</code></a>als Mechanismus verwendet, um verschiedene Indizes miteinander zu verbinden. Allerdings war dies aufgrund teurer Abfragen und unvollständiger Unterstützung in Kibana, insbesondere bei Lens-Visualisierungen, eingeschränkt.</p><p>Dieser Artikel befasst sich eingehend mit dem Zusammenführen zweier Indizes in Elasticsearch und konzentriert sich dabei auf die folgenden Ansätze: </p><ol><li><p>Verwenden der <code>terms</code> -Abfrage</p></li><li><p>Verwenden des <code>enrich</code> -Prozessors in Aufnahmepipelines</p></li><li><p>Logstash <code>elasticsearch</code> Filter-Plugin</p></li><li><p>ES|QL <code>ENRICH</code></p></li><li><p>ES|QL <code>LOOKUP JOIN</code></p></li></ol><h2>Verwenden der Begriffsabfrage</h2><p>Die <a href="https://www.elastic.co/de/docs/reference/query-languages/query-dsl/query-dsl-terms-query">Termabfrage</a> ist eine der effektivsten Möglichkeiten, zwei Indizes in Elasticsearch zu verbinden. Mit dieser Abfrage können Sie Dokumente abrufen, die einen oder mehrere genaue Begriffe in einem bestimmten Feld enthalten. Hier besprechen wir, wie man es zum Verbinden zweier Indizes verwendet.</p><p>Zuerst müssen Sie die erforderlichen Daten aus dem ersten Index abrufen. Dies kann mithilfe einer einfachen GET-Anfrage und dem Abrufen der Werte aus dem Attribut <code>_source</code> erfolgen.</p># Simple GET request
GET first_index/_search<p>Sobald Sie die Daten aus dem ersten Index haben, können Sie diese zum Abfragen des zweiten Index verwenden. Dies geschieht mithilfe der <code>terms</code> -Abfrage, bei der Sie das Feld und die Werte angeben, die Sie abgleichen möchten.</p><p>Hier ist ein Beispiel:</p>GET second_index/_search
{
  "query": {
    "terms": {
      "field_in_second_index": ["value1_from_first_index", "value2_from_first_index"]
    }
  }
}<p>
In diesem Beispiel ist <code>field_in_second_index</code> das Feld im zweiten Index, das Sie mit den Werten aus dem ersten Index abgleichen möchten. <code>value1_from_first_index</code> und <code>value2_from_first_index</code> sind die Werte aus dem ersten Index, die im zweiten Index abgeglichen werden sollen.</p><p>Die Begriffsabfrage bietet außerdem Unterstützung bei der Ausführung der beiden oben genannten Schritte in einem Durchgang mithilfe einer Technik namens <a href="https://www.elastic.co/de/docs/reference/query-languages/query-dsl/query-dsl-terms-query#query-dsl-terms-lookup">„Begriffssuche“</a>. Elasticsearch kümmert sich um das transparente Abrufen der abzugleichenden Werte aus einem anderen Index. Wenn Sie beispielsweise einen Teamindex mit einer Spielerliste haben:</p>PUT teams/_doc/team1
{
  "players":   ["john", "bill", "michael"]
}
PUT teams/_doc/team2
{
  "players":   ["aaron", "joe", "donald"]
}<p>Es ist möglich, einen Personenindex für alle Personen abzufragen, die in Team1 spielen, wie unten gezeigt:</p>GET people/_search?pretty
{
  "query": {
    "terms": {
        "name" : {
            "index" : "teams",
            "id" : "team1",
            "path" : "players"
        }
    }
  }
}<p>Im obigen Beispiel ruft Elasticsearch die Spielernamen transparent aus dem Dokument mit der ID team1 im Teamindex ab (d. h. „John“, „Bill“ und „Michael“) und suchen Sie alle Dokumente im Personenindex, die einen dieser Werte in ihrem Namensfeld enthalten.</p><p>Für alle, die es interessiert: Die entsprechende SQL-Abfrage wäre:</p><h2>Verwenden des Anreicherungsprozessors</h2><p>Der <a href="https://www.elastic.co/de/docs/reference/enrich-processor/enrich-processor"><code>enrich</code></a><a href="https://www.elastic.co/de/docs/reference/enrich-processor/enrich-processor"> -Prozessor</a> ist ein weiteres leistungsstarkes Tool, mit dem zwei Indizes in Elasticsearch verbunden werden können. Dieser Prozessor bereichert die Daten eingehender Dokumente, indem er Daten aus einem vordefinierten Anreicherungsindex hinzufügt.</p><p>So können Sie den Anreicherungsprozessor verwenden, um zwei Indizes zu verknüpfen:</p><p>1. Zuerst müssen Sie eine Anreicherungsrichtlinie erstellen. Diese Richtlinie definiert, welcher Index für die Anreicherung verwendet werden soll, welches Feld abgeglichen werden soll und welche Felder für die Anreicherung eingehender Dokumente verwendet werden sollen.</p><p>Hier ist ein Beispiel:</p>PUT _enrich/policy/my_enrich_policy
{
  "match": {
    "indices": "first_index",
    "match_field": "field_in_first_index",
    "enrich_fields": ["field_to_enrich"]
  }
}<p>2. Sobald die Richtlinie erstellt ist, müssen Sie sie ausführen, um den angereicherten Index aus Ihrer neu erstellten Richtlinie zu erstellen:</p>PUT _enrich/policy/my_enrich_policy/_execute<p>Dadurch wird ein neuer versteckter angereicherter Index erstellt, der während der Anreicherung verwendet wird. Abhängig von der Größe des Quellindex kann dieser Vorgang einige Zeit dauern. Stellen Sie sicher, dass die Anreicherungsrichtlinie vollständig erstellt ist, bevor Sie mit dem nächsten Schritt fortfahren.</p><p>3. Nachdem die Anreicherungsrichtlinie erstellt wurde, können Sie den Anreicherungsprozessor in einer Aufnahmepipeline verwenden, um die Daten eingehender Dokumente anzureichern:</p>PUT _ingest/pipeline/my_pipeline
{
  "processors": [
    {
      "enrich": {
        "policy_name": "my_enrich_policy",
        "field": "field_in_second_index",
        "target_field": "enriched_field"
      }
    }
  ]
}<p>In diesem Beispiel ist <code>field_in_second_index</code> das Feld im zweiten Index, das mit <code>match_field</code> aus dem ersten Index übereinstimmen muss. <code>enriched_field</code> ist das neue Feld im zweiten Index, das die angereicherten Daten aus <code>enrich_fields</code> im ersten Index enthalten wird.</p><p>Ein Nachteil dieses Ansatzes besteht darin, dass die Anreicherungsrichtlinie erneut ausgeführt werden muss, wenn sich die Daten in <code>first_index</code> ändern. Der angereicherte Index wird nicht automatisch mit dem Quellindex aktualisiert oder synchronisiert, aus dem er erstellt wurde. Wenn <code>first_index</code> jedoch relativ stabil ist, funktioniert dieser Ansatz gut.</p><h2>Logstash Elasticsearch-Filter-Plugin</h2><p>Wenn Sie Logstash verwenden, besteht eine weitere Option, die dem oben beschriebenen <code>enrich</code> -Prozessor ähnelt, darin, das <code>elasticsearch</code> -Filter-Plugin zu verwenden, um dem Ereignis basierend auf einer angegebenen Abfrage relevante Felder hinzuzufügen. Die Konfiguration für unsere Logstash-Pipeline würde sich in einer <code>.conf</code> -Datei befinden, beispielsweise <code>my-pipeline.conf</code>.</p><p>Stellen wir uns vor, unsere Pipeline zieht Protokolle aus Elasticsearch mithilfe des <a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-inputs-elasticsearch"><code>elasticsearch</code></a><a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-inputs-elasticsearch"> -Eingabe-Plugins</a> und verwendet eine Abfrage, um die Auswahl einzugrenzen:</p>input {
  # Read all documents from Elasticsearch matching the given query
  elasticsearch {
    hosts =&gt; "localhost"
    query =&gt; '{ "query": { "match": { "statuscode": 200 } }, "sort": [ "_doc" ] }'
  }
}<p>Wenn wir diese Nachrichten mit Informationen aus einem bestimmten Index anreichern möchten, können wir das<a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-filters-elasticsearch"> Filter-Plugin</a> <a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-filters-elasticsearch"><code>elasticsearch</code></a>im Abschnitt <code>filter</code> verwenden, um unsere Protokolle anzureichern:</p>filter {
   elasticsearch {
      hosts =&gt; ["localhost"]
      index =&gt; "index_name"
      query =&gt; "type:start AND operation:%{[opid]}"
      fields =&gt; { "@timestamp" =&gt; "started" }
   }
}<p>Der obige Code findet die Dokumente ab Index <code>index_name</code> , wobei <code>type</code> der Start ist und das Operationsfeld mit dem angegebenen <code>opid</code> übereinstimmt, und kopiert dann den Wert des Felds <code>@timestamp</code> in ein neues Feld mit dem Namen <code>started</code>.</p><p>Die angereicherten Dokumente würden dann an die entsprechende Ausgabequelle gesendet, in diesem Fall an Elasticsearch unter Verwendung des <a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-outputs-elasticsearch"><code>elasticsearch</code></a><a href="https://www.elastic.co/de/docs/reference/logstash/plugins/plugins-outputs-elasticsearch"> -Ausgabe-Plugins</a>:</p>output {
    elasticsearch {
        hosts =&gt; "localhost"
        data_stream =&gt; "true"
    }
}<p>Wenn Sie Logstash bereits verwenden, kann diese Option nützlich sein, um Ihre Anreicherungslogik an einem einzigen Ort zu konsolidieren und bei eingehenden neuen Ereignissen zu verarbeiten. Wenn dies jedoch nicht der Fall ist, wird Ihre Lösung komplexer und Sie müssen eine weitere Komponente ausführen und warten.</p><h2>ES|QL ENRICH</h2><p>Die Einführung von <a href="https://www.elastic.co/de/docs/explore-analyze/query-filter/languages/esql">ES|QL</a>, das in Version 8.14 allgemein verfügbar wurde, ist eine von Elasticsearch unterstützte Piped-Abfragesprache, die das Filtern, Transformieren und Analysieren von Daten ermöglicht. Mithilfe des Verarbeitungsbefehls ENRICH können wir mithilfe einer Anreicherungsrichtlinie Daten aus vorhandenen Indizes hinzufügen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbeb8992bde773461/6a17f6b663baff00c9741dd4/03aadddc08afffff3f6526c9c052999c97fa09dd-1600x989.png" alt="esql bereichern" /><p>Wenn man dieselbe Richtlinie <code>my_enrich_policy</code> aus dem ursprünglichen Beispiel des Anreicherungsprozessors verwendet, würde das ES|QL-Beispiel folgendermaßen aussehen:</p><p>Es ist auch möglich, die Übereinstimmungs- und Anreicherungsfelder zu überschreiben, die in unserem Beispiel <code>field_in_first_index</code> bzw. <code>field_to_enrich</code> sind:</p><p>Die offensichtliche Einschränkung besteht darin, dass Sie zuerst eine Anreicherungsrichtlinie angeben müssen, ES|QL bietet jedoch die Flexibilität, die Felder nach Bedarf anzupassen.</p><h2>ES|QL LOOKUP JOIN</h2><p>Elasticsearch 8.18 führt eine neue Möglichkeit zum Verbinden von Indizes in Elasticsearch ein, nämlich den Befehl <code>LOOKUP JOIN</code> . Dieser Befehl funktioniert als LEFT OUTER JOIN im SQL-Stil und verwendet den neuen <a href="https://www.elastic.co/de/docs/reference/elasticsearch/index-settings/index-modules#index-mode-setting">Lookup-Indexmodus</a> auf der rechten Seite des Joins.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt783ffb3f9802f92d/6a17f6b8e9ea870608a9c788/1d73495979c4d6bb675c4c966ea86d9a72dc1c48-510x605.png" alt="ES|QL LOOKUP JOIN" /><p>Wenn wir unser vorheriges Beispiel noch einmal betrachten, lautet die neue Abfrage wie folgt, wobei <code>match_field</code> sowohl in <code>first_index</code> als auch in <code>second_index</code> vorhanden sein muss:</p><p>Der Vorteil von LOOKUP JOIN gegenüber den anderen Ansätzen besteht darin, dass keine <code>enrich</code> -Richtlinie erforderlich ist und daher auch keine zusätzliche Verarbeitung im Zusammenhang mit der Einrichtung der Richtlinie erforderlich ist. Im Gegensatz zu den anderen in diesem Artikel besprochenen Ansätzen ist es nützlich, wenn mit sich häufig ändernden Anreicherungsdaten gearbeitet wird.</p><h2>Fazit</h2><p>Zusammenfassend lässt sich sagen, dass Elasticsearch zwar keine herkömmlichen Join-Operationen unterstützt, aber verschiedene Funktionen bietet, mit denen ähnliche Ergebnisse erzielt werden können. Insbesondere haben wir erläutert, wie Sie Join-Operationen mithilfe der folgenden Methoden durchführen können:</p><ol><li><p>Die <code>terms</code> -Abfrage</p></li><li><p>Der <code>enrich</code> -Prozessor in Ingest-Pipelines</p></li><li><p>Logstash <code>elasticsearch</code> Filter-Plugin</p></li><li><p>ES|QL <code>ENRICH</code></p></li><li><p>ES|QL <code>LOOKUP JOIN</code></p></li></ol><p>Es ist wichtig zu beachten, dass diese Methoden ihre Grenzen haben und je nach den spezifischen Anforderungen und der Art der Daten mit Bedacht eingesetzt werden sollten.</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[Grundlagen]]></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[Verwendung der hybriden Suche für die Gopher-Jagd mit Elasticsearch und Go]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie mit Elasticsearch und dem Elasticsearch Go-Client eine hybride Suche realisieren, indem Sie Keyword- und Vektorsuche kombinieren.]]></description>
    <content:encoded><![CDATA[<p>In den vorherigen Teilen dieser Serie wurde gezeigt, wie man den Elasticsearch Go-Client für <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">die traditionelle Stichwortsuche</a> und <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">die Vektorsuche</a> verwendet. Dieser dritte Teil behandelt die hybride Suche. Wir zeigen Ihnen <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">Beispiele</a> , wie Sie Vektorsuche und Stichwortsuche mit <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> und dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a> kombinieren können.</p><h2>Voraussetzungen</h2><p>Genau wie im ersten Teil dieser Reihe gelten auch für dieses Beispiel folgende Voraussetzungen:</p><ol><li><p>Installation von Go Version 1.21 oder höher</p></li><li><p>Erstellen Sie Ihr eigenes Go-Repository gemäß der in der <a href="https://go.dev/doc/code">Go-Dokumentation</a>beschriebenen empfohlenen Struktur und Paketverwaltung.</p></li><li><p>Erstellen eines eigenen Elasticsearch-Clusters, gefüllt mit einer Reihe von <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">Seiten über Nagetiere</a>, darunter auch für unseren freundlichen <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, aus Wikipedia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia-Seite über Gopher" /><h2>Verbindung zu Elasticsearch herstellen</h2><p>Zur Erinnerung: In unseren Beispielen werden wir die vom Go-Client angebotene <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a> verwenden. Um eine sichere Verbindung für jede Anfrage herzustellen, muss der Client auf folgende Weise konfiguriert werden:</p><ol><li><p>Cloud-ID und API-Schlüssel bei Verwendung von Elastic Cloud</p></li><li><p>Cluster-URL, Benutzername, Passwort und Zertifikat</p></li></ol><p>Die Verbindung zu unserem Cluster in der Elastic Cloud würde folgendermaßen aussehen:</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>Die <code>client</code> -Verbindung kann dann für Suchvorgänge verwendet werden, wie in den nachfolgenden Abschnitten gezeigt wird.</p><h2>Manuelles Boosting für Hybridsuche</h2><p>Bei der Kombination beliebiger Suchalgorithmen bestand der traditionelle Ansatz darin, Konstanten manuell zu konfigurieren, um jeden Abfragetyp zu verstärken. Genauer gesagt wird für jede Anfrage ein Faktor festgelegt, und das kombinierte Ergebnisset wird mit dem erwarteten Set verglichen, um die Trefferquote der Anfrage zu bestimmen. Dann wiederholen wir den Vorgang für mehrere Faktorensätze und wählen denjenigen aus, der unserem gewünschten Zustand am nächsten kommt.</p><p>Beispielsweise kann die Kombination einer einzelnen Textsuchanfrage mit einem Gewichtungsfaktor von <code>0.8</code> mit einer kNN-Abfrage mit einem niedrigeren Gewichtungsfaktor von <code>0.2</code> durch Angabe des Feldes <code>Boost</code> in beiden Abfragetypen erfolgen, wie im folgenden Beispiel gezeigt:</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>Der in der Option <code>Boost</code> für jede Abfrage angegebene Faktor wird zur Dokumentbewertung addiert. Indem wir den Score unserer Match-Abfrage um einen größeren Faktor erhöhen als den der KNN-Abfrage, werden die Ergebnisse der Keyword-Abfrage stärker gewichtet.</p><p>Die Herausforderung beim manuellen Boosting, insbesondere wenn man kein Suchmaschinenexperte ist, besteht darin, dass es eine Feinabstimmung erfordert, um die Faktoren herauszufinden, die zum gewünschten Ergebnis führen. Es geht einfach darum, verschiedene Werte auszuprobieren, um zu sehen, welcher Wert Sie dem gewünschten Ergebnis näherbringt.</p><h2>Reciprocal Rank Fusion in hybrid search &amp; Go client</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">Reciprocal Rank Fusion</a>, oder RRF, wurde in Elasticsearch 8.9 als technische Vorschau für die hybride Suche veröffentlicht. Ziel ist es, den Lernaufwand für die Feinabstimmung zu reduzieren und den Zeitaufwand für das Experimentieren mit Faktoren zur Optimierung des Ergebnissatzes zu verringern.</p><p>Bei RRF wird die Dokumentenbewertung durch Mischen der Bewertungen mithilfe des folgenden Algorithmus neu berechnet:</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>Der Vorteil der Verwendung von RRF besteht darin, dass wir die sinnvollen Standardwerte in Elasticsearch nutzen können. Die Rangkonstante <code>k</code> ist standardmäßig auf <code>60</code> gesetzt. Um einen Kompromiss zwischen der Relevanz der zurückgegebenen Dokumente und der Abfrageleistung bei der Suche in großen Datensätzen zu erzielen, ist die Größe des Ergebnissatzes für jede betrachtete Abfrage auf den Wert <code>window_size</code> begrenzt, der standardmäßig auf <code>100</code> eingestellt ist, wie in der <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html#rrf-api">Dokumentation</a> beschrieben.</p><p><code>k</code> und <code>windows_size</code> kann auch innerhalb der <code>Rrf</code> -Konfiguration innerhalb der <code>Rank</code> -Methode im Go-Client konfiguriert werden, wie im folgenden Beispiel gezeigt:</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>Fazit</h2><p>Hier haben wir besprochen, wie man Vektor- und Stichwortsuche in Elasticsearch mithilfe des <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Clients</a> kombiniert.</p><p>Im <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub-Repository</a> findet ihr den gesamten Code dieser Serie. Falls Sie es noch nicht getan haben, schauen Sie sich <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">Teil 1</a> und <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">Teil 2</a> an, um den gesamten Code dieser Serie zu finden.</p><p><em>Viel Spaß bei der Gopherjagd!</em></p><h2>Ressourcen</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch-Leitfaden</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">Was ist Vektorsuche? | Elastisch</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">Reziproke Rangfusion</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[Vektordatenbank]]></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[Führen Sie eine Vektorsuche in Elasticsearch mit dem Elasticsearch Go-Client durch.]]></title>
    <description><![CDATA[Lernen Sie anhand eines praktischen Beispiels, wie Sie mit dem Elasticsearch Go-Client eine Vektorsuche in Elasticsearch durchführen.]]></description>
    <content:encoded><![CDATA[<p>Softwareentwicklung in jeder Programmiersprache, einschließlich Go, bedeutet die Verpflichtung zu lebenslangem Lernen. Während ihrer Universitäts- und Berufslaufbahn hat Carly mit vielen Programmiersprachen und Technologien experimentiert, darunter auch mit den neuesten und besten Implementierungen der Vektorsuche. Aber das reichte nicht! Seit Kurzem spielt auch Carly Go.</p><p>Genau wie Tiere, Programmiersprachen und Ihr freundlicher Autor hat sich auch die Suche im Laufe der Zeit weiterentwickelt und verschiedene Praktiken hervorgebracht, bei denen es schwierig sein kann, die richtige für Ihren individuellen Anwendungsfall zu finden. In diesem Blog geben wir einen Überblick über die Vektorsuche und zeigen <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">Beispiele</a> für die einzelnen Ansätze mit <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> und dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a>. Anhand dieser Beispiele wird Ihnen gezeigt, wie Sie mit Hilfe der Vektorsuche in Elasticsearch und Go Taschenratten finden und deren Nahrung bestimmen können.</p><h2>Voraussetzungen</h2><p>Um diesem Beispiel folgen zu können, stellen Sie sicher, dass die folgenden Voraussetzungen erfüllt sind:</p><ol><li><p>Installation von Go Version 1.21 oder höher</p></li><li><p>Erstellung eines eigenen Go-Repositorys mit dem</p></li><li><p>Erstellung eines eigenen Elasticsearch-Clusters, gefüllt mit einer Reihe von Seiten über Nagetiere, darunter auch für unseren freundlichen <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, aus Wikipedia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia-Seite über Gopher" /><h2>Verbindung zu Elasticsearch herstellen</h2><p>In unseren Beispielen werden wir die vom Go-Client angebotene <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a> verwenden. Um eine sichere Verbindung für jede Anfrage herzustellen, muss der Client auf folgende Weise konfiguriert werden:</p><ol><li><p>Cloud-ID und API-Schlüssel bei Verwendung von Elastic Cloud.</p></li><li><p>Cluster-URL, Benutzername, Passwort und Zertifikat.</p></li></ol><p>Die Verbindung zu unserem Cluster in der Elastic Cloud würde folgendermaßen aussehen:</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>Die <code>client</code> -Verbindung kann dann für die Vektorsuche verwendet werden, wie in den nachfolgenden Abschnitten gezeigt wird.</p><h2>Vektorsuche</h2><p>Die Vektorsuche versucht, dieses Problem zu lösen, indem sie das Suchproblem in einen mathematischen Vergleich mithilfe von Vektoren umwandelt. Der Dokumenteneinbettungsprozess beinhaltet einen zusätzlichen Schritt, bei dem das Dokument mithilfe eines Modells in eine dichte Vektordarstellung oder einfach in einen Zahlenstrom umgewandelt wird. Der Vorteil dieses Ansatzes besteht darin, dass man auch nicht-textuelle Dokumente wie Bilder und Audiodateien durchsuchen kann, indem man sie zusammen mit einer Suchanfrage in einen Vektor übersetzt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4b3b9b2ad1e8f46/6a1704d06234e0800fdb1927/b113358093e367358d684f7aaf0a6684ebb2d0dd-1440x653.png" alt="Vektorsuchdiagramm" /><p>Vereinfacht ausgedrückt ist die Vektorsuche eine Reihe von Vektordistanzberechnungen. In der folgenden Abbildung wird die Vektordarstellung unserer Anfrage <code>Go Gopher</code>mit den Dokumenten im Vektorraum verglichen, und die nächstliegenden Ergebnisse (gekennzeichnet durch die Konstante <code>k</code>) werden zurückgegeben:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c736ecfc49bb038/6a1704d2cf4f25bcb6b2d075/54a17a4b41029644e7c66f33d428e8d01a6f4ce3-1184x743.png" alt="Gopher-Vektorraum-Beispiel" /><p>Je nachdem, welcher Ansatz zur Generierung der Einbettungen für Ihre Dokumente verwendet wird, gibt es zwei verschiedene Wege, um herauszufinden, was Taschenratten fressen.</p><h3>Ansatz 1: Bringen Sie Ihr eigenes Modell mit</h3><p>Mit einer Platinum-Lizenz ist es möglich, die Einbettungen innerhalb von Elasticsearch zu generieren, indem das Modell hochgeladen und die Inferenz-API verwendet wird. Die Einrichtung des Modells umfasst sechs Schritte:</p><ol><li><p>Wählen Sie ein PyTorch-Modell aus einem Modell-Repository zum Hochladen aus. Für dieses Beispiel verwenden wir den <a href="https://huggingface.co/sentence-transformers/msmarco-MiniLM-L-12-v3">sentence-transformers/msmarco-MiniLM-L-12-v3</a> von Hugging Face, um die Einbettungen zu generieren.</p></li><li><p>Laden Sie das Modell in Elastic mit dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/eland/current/overview.html">Eland Machine Learning Client für Python</a> unter Verwendung der Anmeldeinformationen für unseren Elasticsearch-Cluster und dem Aufgabentyp <code>text_embeddings</code>. Falls Eland nicht installiert ist, können Sie <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-import-model.html#ml-nlp-import-docker">den Import-Schritt mit Docker ausführen</a>, wie unten gezeigt:</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>Nach dem Hochladen sollte das Modell <code>sentence-transformers__msmarco-minilm-l-12-v3</code> schnell mit einem Beispieldokument getestet werden, um sicherzustellen, dass die Einbettungen wie erwartet generiert werden:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a399e1f50ecfdaf/6a1704d4ab7f08935edb9d78/fbbdde621361a487eb07304bed029c228d0f7aa6-1440x789.png" alt="Beispiel für ein trainiertes Modell im Elastizitätstest" /><ol><li><p>Erstellen Sie eine Ingest-Pipeline, die einen Inferenzprozessor enthält. Dadurch kann die Vektordarstellung mithilfe des hochgeladenen Modells generiert werden:</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>Erstellen Sie einen neuen Index, der das Feld <code>text_embedding.predicted_value</code> vom Typ <code>dense_vector</code> enthält, um die für jedes Dokument generierten Vektoreinbettungen zu speichern:</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>Die Dokumente werden mithilfe der neu erstellten Ingest-Pipeline neu indiziert, um die Text-Embeddings als zusätzliches Feld <code>text_embedding.predicted_value</code> in jedem Dokument zu generieren:</p></li></ol>POST _reindex
{
  "source": {
    "index": "search-rodents"
  },
  "dest": {
    "index": "vector-search-rodents",
    "pipeline": "search-rodents-vector-embedding-pipeline"
  }
}
<p>Nun können wir die Option <code>Knn</code> in derselben Such-API mit dem neuen Index <code>vector-search-rodents</code> verwenden, wie im folgenden Beispiel gezeigt:</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>Die Konvertierung des JSON-Ergebnisobjekts mittels Unmarshalling erfolgt auf genau die gleiche Weise wie im Beispiel der Stichwortsuche. Mithilfe der Konstanten <code>K</code> und <code>NumCandidates</code> können wir die Anzahl der zurückzugebenden Nachbardokumente und die Anzahl der pro Shard zu berücksichtigenden Kandidaten konfigurieren. Beachten Sie, dass eine Erhöhung der Anzahl der Kandidaten zwar die Genauigkeit der Ergebnisse erhöht, aber zu einer längeren Abfragedauer führt, da mehr Vergleiche durchgeführt werden.</p><p>Wird der Code mit der Abfrage <code>What do Gophers eat?</code> ausgeführt, sehen die zurückgegebenen Ergebnisse ähnlich wie unten dargestellt aus, was verdeutlicht, dass der Gopher-Artikel im Gegensatz zur vorherigen Stichwortsuche die angeforderten Informationen enthält:</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>Ansatz 2: Hugging Face Inference API</h3><p>Eine weitere Möglichkeit besteht darin, diese Einbettungen außerhalb von Elasticsearch zu generieren und sie als Teil Ihres Dokuments einzubinden. Da diese Option keinen Elasticsearch Machine Learning-Knoten verwendet, kann sie im kostenlosen Tarif durchgeführt werden.</p><p>Hugging Face stellt eine kostenlose, ratenbegrenzte <a href="https://huggingface.co/docs/api-inference/index">Inferenz-API</a> zur Verfügung, mit der Sie mithilfe eines Kontos und eines API-Tokens dieselben Einbettungen manuell für Experimente und Prototyping generieren können, um Ihnen den Einstieg zu erleichtern. Für den Einsatz in der Produktion wird es nicht empfohlen. Das lokale Aufrufen eigener Modelle zur Generierung von Einbettungen oder die Nutzung der kostenpflichtigen API kann ebenfalls mit einem ähnlichen Ansatz erfolgen.</p><p>In der folgenden Funktion <code>GetTextEmbeddingForQuery</code> verwenden wir die Inferenz-API anhand unserer Abfragezeichenfolge, um den Vektor zu generieren, der von einer <code>POST</code> Anfrage an den Endpunkt zurückgegeben wird:</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>Der resultierende Vektor vom Typ <code>[]float32</code> wird dann als <code>QueryVector</code> übergeben, anstatt die Option <code>QueryVectorBuilder</code> zu verwenden, um das zuvor in Elastic hochgeladene Modell zu nutzen.</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>Beachten Sie, dass die Optionen <code>K</code> und <code>NumCandidates</code> unabhängig von den beiden Optionen gleich bleiben und dass die gleichen Ergebnisse generiert werden, da wir dasselbe Modell zur Generierung der Einbettungen verwenden.</p><h2>Fazit</h2><p>Hier haben wir besprochen, wie man eine Vektorsuche in Elasticsearch mit dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a> durchführt. Im <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub-Repository</a> findet ihr den gesamten Code dieser Serie. Im Anschluss daran lesen Sie <a href="https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client">Teil 3,</a> um einen Überblick über die Kombination der Vektorsuche mit den in <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">Teil eins</a> behandelten Schlüsselwortsuchfunktionen in Go zu erhalten.</p><p>Bis dahin, viel Erfolg bei der Gopherjagd!</p><h2>Ressourcen</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch-Leitfaden</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">Was ist Vektorsuche? | Elastisch</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[Vektordatenbank]]></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[Führen Sie Textabfragen mit dem Elasticsearch Go-Client durch.]]></title>
    <description><![CDATA[Lernen Sie anhand eines praktischen Beispiels, wie Sie mit dem Elasticsearch Go-Client herkömmliche Textabfragen in Elasticsearch durchführen.]]></description>
    <content:encoded><![CDATA[<p>Softwareentwicklung in jeder Programmiersprache, einschließlich Go, bedeutet die Verpflichtung zu lebenslangem Lernen. Während ihrer gesamten Universitäts- und Berufslaufbahn musste sich Carly an die Polyglotte anpassen und sich mit vielen Programmiersprachen auseinandersetzen, darunter Python, C, JavaScript, TypeScript und Java. Aber das reichte nicht! Seit Kurzem spielt sie auch Go!</p><p>Genau wie Tiere, Programmiersprachen und auch einige Ihrer Lieblingsautoren hat sich die Suche im Laufe der Zeit weiterentwickelt und verschiedene Vorgehensweisen hervorgebracht, bei denen es schwierig sein kann, die richtige für Ihren individuellen Anwendungsfall zu finden. In diesem Blog geben wir einen Überblick über die traditionelle Stichwortsuche und stellen <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">ein Beispiel</a> mit <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> und dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a> vor.</p><h2>Voraussetzungen</h2><p>Um diesem Beispiel folgen zu können, stellen Sie sicher, dass die folgenden Voraussetzungen erfüllt sind:</p><ol><li><p>Installation von Go Version 1.21 oder höher</p></li><li><p>Erstellen Sie Ihr eigenes Go-Repository gemäß der in der <a href="https://go.dev/doc/code">Go-Dokumentation</a>beschriebenen empfohlenen Struktur und Paketverwaltung.</p></li><li><p>Erstellung eines eigenen Elasticsearch-Clusters, gefüllt mit einer Reihe von <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">Seiten über Nagetiere,</a> darunter auch für unseren freundlichen <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, aus Wikipedia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Wikipedia-Seite über Gopher" /><h2>Verbindung zu Elasticsearch herstellen</h2><p>In unseren Beispielen werden wir die vom Go-Client angebotene <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API</a> verwenden. Um eine sichere Verbindung für jede Anfrage herzustellen, muss der Client auf folgende Weise konfiguriert werden:</p><ol><li><p>Cloud-ID und API-Schlüssel bei Verwendung von Elastic Cloud.</p></li><li><p>Cluster-URL, Benutzername, Passwort und Zertifikat.</p></li></ol><p>Die Verbindung zu unserem Cluster in der Elastic Cloud würde folgendermaßen aussehen:</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>Die <code>client</code> -Verbindung kann dann, wie später gezeigt wird, für die Suche verwendet werden.</p><h2>Stichwortsuche</h2><p>Die Stichwortsuche ist die grundlegende Suchart, mit der wir seit der Entwicklung von <a href="https://en.wikipedia.org/wiki/Archie_(search_engine)">Archie</a>, der ersten dokumentierten Internet-Suchmaschine aus dem Jahr 1990, vertraut sind.</p><p>Ein zentraler Bestandteil der Stichwortsuche ist die Übersetzung von Dokumenten in einen invertierten Index. Genau wie das Register am Ende eines Lehrbuchs enthält ein invertiertes Register eine Zuordnung zwischen einer Liste von Tokens und deren Position in jedem Dokument. Das folgende Diagramm zeigt die wichtigsten Schritte der Indexerstellung:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt366681a12027f14b/6a17e7aa1d1b831c2093e452/9cd7b2a60d9aa54facb37738b821bba6ca925830-1440x581.png" alt="Invertierte Indexgenerierung" /><p>Wie oben dargestellt, umfasst die Token-Generierung in Elasticsearch drei Hauptphasen:</p><ol><li><p>Entfernen unnötiger Zeichen durch Null oder mehr <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html"><code>char_filters</code></a>. In unserem Beispiel entfernen wir HTML-Elemente innerhalb des Feldes <code>body_content</code> mithilfe des Filters <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html"><code>html_strip</code></a> .</p></li><li><p>Die Tokens werden mithilfe des <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"> Tokenizers</a> vom Inhalt getrennt, wobei die Trennung anhand von Leerzeichen und Satzzeichen erfolgt.</p></li><li><p>Unerwünschte Tokens werden aus dem Ausgabestream des Tokenizers entfernt oder Tokens mithilfe von null oder mehr <code>filter</code> -Optionen transformiert, z. B. durch den <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"> -Tokenfilter</a> oder Stemmer wie den <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"> -Stemmer</a> , um Tokens wieder in ihre Sprachwurzel umzuwandeln.</p></li></ol><h2>Suche in Elasticsearch mit Go</h2><p>Bei Abfragen mit dem Go-Client geben wir den zu durchsuchenden Index an und übergeben die Abfrage sowie weitere Optionen, wie im folgenden Beispiel:</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>Im obigen Beispiel führen wir eine<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"> Standardabfrage</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"><code>match</code></a>durch, um alle Dokumente in unserem Index zu finden, die die an unsere Funktion übergebene Zeichenkette enthalten. Beachten Sie, dass wir über <code>Do(context.Background())</code> einen <a href="https://pkg.go.dev/context#Background">neuen leeren Kontext</a> an die Suchausführung übergeben. Darüber hinaus werden alle von Elasticsearch zurückgegebenen Fehler zur Protokollierung und Fehlerbehandlung an das Attribut <code>err</code> ausgegeben.</p><p>Die Ergebnisse werden in <code>res.Hits.Hits</code> zurückgegeben, wobei das Attribut <code>_Source</code> das Dokument selbst im JSON-Format enthält. Um diese Quelle in eine Go-kompatible Struktur umzuwandeln, müssen wir die JSON-Antwort mithilfe des Go <a href="https://pkg.go.dev/encoding/json">-Pakets encoding/json</a> <a href="https://pkg.go.dev/encoding/json#Unmarshal">deserialisieren</a>, wie im folgenden Beispiel gezeigt:</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>Die Suche und das Unmarshalling der Anfrage <code>gopher</code> liefert wie erwartet die Wikipedia-Seite für Gopher zurück:</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher}
]
<p>Wenn wir jedoch <code>What do Gophers eat?</code> fragen, erhalten wir nicht ganz die gewünschten Ergebnisse:</p>[]
<p>Eine einfache Stichwortsuche ermöglicht es, Ergebnisse performant an Ihre Go-Anwendung zurückzugeben, und zwar auf eine Weise, die wir von den Anwendungen, die wir verwenden, gewohnt sind. Es eignet sich auch hervorragend für exakte Suchbegriffübereinstimmungen, die für Szenarien wie die Suche nach einem bestimmten Unternehmen oder Begriff relevant sind.</p><p>Wie wir oben sehen, hat es jedoch aufgrund des Vokabular-Diskrepanzen Probleme, Kontext und Semantik zu identifizieren. Darüber hinaus stellt die Unterstützung von Nicht-Text-Dateiformaten wie Bildern und Audiodateien eine Herausforderung dar.</p><h2>Fazit</h2><p>Hier haben wir besprochen, wie man mit dem <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a> herkömmliche Textabfragen in Elasticsearch durchführt. Da Go häufig für die Skripterstellung im Infrastrukturbereich und den Aufbau von Webservern verwendet wird, ist es nützlich zu wissen, wie man in Go sucht.</p><p>Im <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">GitHub-Repository</a> findet ihr den gesamten Code dieser Serie. Im Anschluss daran folgt <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">Teil 2,</a> um einen Überblick über die Vektorsuche und deren Durchführung in Go zu erhalten. Bis dahin, viel Erfolg bei der Gopherjagd!</p><h2>Ressourcen</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch-Leitfaden</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go-Client</a></p></li><li><p><a href="https://codingexplained.com/coding/elasticsearch/understanding-analysis-in-elasticsearch-analyzers">Analysefunktionen in Elasticsearch verstehen (Analysatoren) von 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>