<?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[Go - 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[Go - 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/blog/category/go-programming</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/blog/category/go-programming</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/category/go-programming.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 19:52:36 GMT</lastBuildDate>
  <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>