<?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/pt/search-labs/blog/category/go-programming</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/blog/category/go-programming</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/category/go-programming.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 20:53:43 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Usando busca híbrida para caça de gopher com Elasticsearch e Go]]></title>
    <description><![CDATA[Aprenda como realizar buscas híbridas combinando buscas por palavra-chave e buscas vetoriais usando o Elasticsearch e o cliente Elasticsearch Go.]]></description>
    <content:encoded><![CDATA[<p>Nas partes anteriores desta série, foi demonstrado como usar o cliente Elasticsearch Go para <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">pesquisa tradicional por palavras-chave</a> e <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">pesquisa vetorial</a>. Esta terceira parte aborda a busca híbrida. Vamos compartilhar <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">exemplos</a> de como você pode combinar a pesquisa vetorial e a pesquisa por palavra-chave usando o <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> e o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>.</p><h2>Pré-requisitos</h2><p>Assim como na primeira parte desta série, os seguintes pré-requisitos são necessários para este exemplo:</p><ol><li><p>Instalação do Go versão 1.21 ou posterior</p></li><li><p>Crie seu próprio repositório Go usando a estrutura recomendada e o gerenciamento de pacotes abordados na <a href="https://go.dev/doc/code">documentação do Go.</a></p></li><li><p>Criando seu próprio cluster Elasticsearch, preenchido com um conjunto de <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">páginas baseadas em roedores</a>, incluindo para o nosso amigável <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, da Wikipédia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Página do Gopher na Wikipédia" /><h2>Conectando-se ao Elasticsearch</h2><p>Lembrando que, em nossos exemplos, utilizaremos a <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">API tipada</a> oferecida pelo cliente Go. Para estabelecer uma conexão segura para qualquer consulta, é necessário configurar o cliente usando um dos seguintes métodos:</p><ol><li><p>ID da nuvem e chave de API, caso esteja utilizando o Elastic Cloud.</p></li><li><p>URL do cluster, nome de usuário, senha e certificado</p></li></ol><p>A conexão com nosso cluster localizado no Elastic Cloud seria feita da seguinte forma:</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>A conexão <code>client</code> pode então ser usada para pesquisa, como demonstrado nas seções subsequentes.</p><h2>Impulsionamento manual para pesquisa híbrida</h2><p>Ao combinar qualquer conjunto de algoritmos de busca, a abordagem tradicional tem sido configurar manualmente constantes para otimizar cada tipo de consulta. Especificamente, um fator é definido para cada consulta, e o conjunto de resultados combinados é comparado ao conjunto esperado para determinar a recuperação da consulta. Em seguida, repetimos o processo para vários conjuntos de fatores e escolhemos aquele que mais se aproxima do estado desejado.</p><p>Por exemplo, combinar uma consulta de pesquisa de texto simples, ampliada por um fator de <code>0.8</code> , com uma consulta KNN com um fator menor de <code>0.2</code> pode ser feito especificando o campo <code>Boost</code> em ambos os tipos de consulta, como mostrado no exemplo abaixo:</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>O fator especificado na opção <code>Boost</code> para cada consulta é adicionado à pontuação do documento. Ao aumentar a pontuação da nossa consulta de correspondência por um fator maior do que a consulta knn, os resultados da consulta por palavra-chave recebem um peso maior.</p><p>O desafio da otimização manual, especialmente se você não for um especialista em buscas, é que ela exige ajustes para descobrir os fatores que levarão ao conjunto de resultados desejado. Trata-se simplesmente de experimentar valores aleatórios para ver o que o aproxima do resultado desejado.</p><h2>Fusão de classificação recíproca em pesquisa híbrida e cliente Go</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">O Reciprocal Rank Fusion</a>, ou RRF, foi lançado em versão de pré-visualização técnica para busca híbrida no Elasticsearch 8.9. Tem como objetivo reduzir a curva de aprendizado associada ao ajuste fino e diminuir o tempo gasto experimentando diferentes fatores para otimizar o conjunto de resultados.</p><p>Com o RRF, a pontuação do documento é recalculada combinando as pontuações pelo algoritmo abaixo:</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>A vantagem de usar o RRF é que podemos aproveitar os valores padrão adequados do Elasticsearch. A constante de classificação <code>k</code> assume o valor padrão <code>60</code>. Para proporcionar um equilíbrio entre a relevância dos documentos retornados e o desempenho da consulta ao pesquisar em grandes conjuntos de dados, o tamanho do conjunto de resultados para cada consulta considerada é limitado ao valor de <code>window_size</code>, que por padrão é <code>100</code> conforme descrito na <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html#rrf-api">documentação</a>.</p><p><code>k</code> e <code>windows_size</code> também pode ser configurado dentro da configuração <code>Rrf</code> dentro do método <code>Rank</code> no cliente Go, conforme o exemplo abaixo:</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>Conclusão</h2><p>Aqui discutimos como combinar a pesquisa vetorial e a pesquisa por palavra-chave no Elasticsearch usando o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>.</p><p>Confira o <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">repositório do GitHub</a> para acessar todo o código desta série. Caso ainda não tenha feito, confira <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">a parte 1</a> e <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">a parte 2</a> para ver todo o código desta série.</p><p><em>Boa caçada aos esquilos!</em></p><h2>Recursos</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Guia do Elasticsearch</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Cliente Go do Elasticsearch</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">O que é busca vetorial? | Elástico</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">Fusão de Classificação Recíproca</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[Banco de dados vetorial]]></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[Realize buscas vetoriais no Elasticsearch com o cliente Elasticsearch Go.]]></title>
    <description><![CDATA[Aprenda como realizar buscas vetoriais no Elasticsearch usando o cliente Elasticsearch Go por meio de um exemplo prático.]]></description>
    <content:encoded><![CDATA[<p>Desenvolver software em qualquer linguagem de programação, incluindo Go, é comprometer-se com uma vida inteira de aprendizado. Ao longo de sua trajetória acadêmica e profissional, Carly explorou diversas linguagens de programação e tecnologias, incluindo as mais recentes e melhores implementações de busca vetorial. Mas isso não foi suficiente! Recentemente, Carly também começou a jogar Go.</p><p>Assim como os animais, as linguagens de programação e seu amigável autor, a busca passou por uma evolução de diferentes práticas, o que pode dificultar a escolha da melhor opção para o seu caso específico. Neste blog, compartilharemos uma visão geral da busca vetorial, juntamente com <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">exemplos</a> de cada abordagem usando <a href="https://www.elastic.co/elasticsearch/">o Elasticsearch</a> e o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>. Estes exemplos mostrarão como encontrar esquilos-da-terra e determinar o que eles comem usando a busca vetorial no Elasticsearch e em Go.</p><h2>Pré-requisitos</h2><p>Para dar continuidade a este exemplo, certifique-se de que os seguintes pré-requisitos sejam atendidos:</p><ol><li><p>Instalação do Go versão 1.21 ou posterior</p></li><li><p>Criação do seu próprio repositório Go com o</p></li><li><p>Criação do seu próprio cluster Elasticsearch, preenchido com um conjunto de páginas baseadas em roedores, incluindo para o nosso amigável <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, da Wikipédia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Página do Gopher na Wikipédia" /><h2>Conectando-se ao Elasticsearch</h2><p>Em nossos exemplos, utilizaremos a <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">API tipada</a> oferecida pelo cliente Go. Para estabelecer uma conexão segura para qualquer consulta, é necessário configurar o cliente usando um dos seguintes métodos:</p><ol><li><p>ID da nuvem e chave de API, caso esteja utilizando o Elastic Cloud.</p></li><li><p>URL do cluster, nome de usuário, senha e certificado.</p></li></ol><p>A conexão com nosso cluster localizado no Elastic Cloud seria feita da seguinte forma:</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>A conexão <code>client</code> pode então ser usada para busca vetorial, como mostrado nas seções subsequentes.</p><h2>Busca vetorial</h2><p>A busca vetorial tenta resolver esse problema convertendo-o em uma comparação matemática usando vetores. O processo de incorporação de documentos possui uma etapa adicional de conversão do documento, utilizando um modelo, em uma representação vetorial densa, ou simplesmente em um fluxo de números. A vantagem dessa abordagem é que você pode pesquisar documentos não textuais, como imagens e áudio, convertendo-os em um vetor juntamente com uma consulta.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4b3b9b2ad1e8f46/6a1704d06234e0800fdb1927/b113358093e367358d684f7aaf0a6684ebb2d0dd-1440x653.png" alt="Diagrama de Busca Vetorial" /><p>Em termos simples, a busca vetorial é um conjunto de cálculos de distância vetorial. Na ilustração abaixo, a representação vetorial da nossa consulta <code>Go Gopher</code>é comparada com os documentos no espaço vetorial, e os resultados mais próximos (denotados pela constante <code>k</code>) são retornados:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c736ecfc49bb038/6a1704d2cf4f25bcb6b2d075/54a17a4b41029644e7c66f33d428e8d01a6f4ce3-1184x743.png" alt="Exemplo de espaço vetorial Gopher" /><p>Dependendo da abordagem usada para gerar os embeddings dos seus documentos, existem duas maneiras diferentes de descobrir o que os gophers comem.</p><h3>Abordagem 1: Traga seu próprio modelo</h3><p>Com uma licença Platinum, é possível gerar os embeddings dentro do Elasticsearch, carregando o modelo e usando a API de inferência. A configuração do modelo envolve seis etapas:</p><ol><li><p>Selecione um modelo PyTorch para carregar a partir de um repositório de modelos. Neste exemplo, estamos usando o <a href="https://huggingface.co/sentence-transformers/msmarco-MiniLM-L-12-v3">sentence-transformers/msmarco-MiniLM-L-12-v3</a> da Hugging Face para gerar os embeddings.</p></li><li><p>Carregue o modelo no Elastic usando o <a href="https://www.elastic.co/guide/en/elasticsearch/client/eland/current/overview.html">cliente Eland Machine Learning para Python</a> usando as credenciais para nosso cluster Elasticsearch e tipo de tarefa <code>text_embeddings</code>. Se você não tiver o Eland instalado, poderá <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-import-model.html#ml-nlp-import-docker">executar a etapa de importação usando o Docker</a>, conforme mostrado abaixo:</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>Após o carregamento, teste rapidamente o modelo <code>sentence-transformers__msmarco-minilm-l-12-v3</code> com um documento de exemplo para garantir que os embeddings sejam gerados conforme o esperado:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a399e1f50ecfdaf/6a1704d4ab7f08935edb9d78/fbbdde621361a487eb07304bed029c228d0f7aa6-1440x789.png" alt="Exemplo de modelo treinado no Elastic Test" /><ol><li><p>Crie um pipeline de ingestão contendo um processador de inferência. Isso permitirá que a representação vetorial seja gerada usando o modelo carregado:</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>Crie um novo índice contendo o campo <code>text_embedding.predicted_value</code> do tipo <code>dense_vector</code> para armazenar os vetores de incorporação gerados para cada documento:</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>Reindexe os documentos usando o pipeline de ingestão recém-criado para gerar os embeddings de texto como o campo adicional <code>text_embedding.predicted_value</code> em cada documento:</p></li></ol>POST _reindex
{
  "source": {
    "index": "search-rodents"
  },
  "dest": {
    "index": "vector-search-rodents",
    "pipeline": "search-rodents-vector-embedding-pipeline"
  }
}
<p>Agora podemos usar a opção <code>Knn</code> na mesma API de pesquisa usando o novo índice <code>vector-search-rodents</code>, como mostrado no exemplo abaixo:</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>A conversão do objeto JSON resultante por meio de desserialização é feita exatamente da mesma forma que no exemplo de pesquisa por palavra-chave. As constantes <code>K</code> e <code>NumCandidates</code> permitem configurar o número de documentos vizinhos a serem retornados e o número de candidatos a serem considerados por fragmento. Note que aumentar o número de candidatos aumenta a precisão dos resultados, mas leva a uma consulta mais demorada, pois mais comparações são realizadas.</p><p>Quando o código é executado usando a consulta <code>What do Gophers eat?</code>, os resultados retornados são semelhantes aos abaixo, destacando que o artigo do Gopher contém as informações solicitadas, diferentemente da pesquisa anterior por palavra-chave:</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>Abordagem 2: API de inferência do Hugging Face</h3><p>Outra opção é gerar esses mesmos embeddings fora do Elasticsearch e ingeri-los como parte do seu documento. Como essa opção não utiliza um nó de aprendizado de máquina do Elasticsearch, ela pode ser executada no nível gratuito.</p><p>A Hugging Face disponibiliza uma <a href="https://huggingface.co/docs/api-inference/index">API de inferência</a> gratuita e com limite de requisições que, mediante uma conta e um token de API, pode ser usada para gerar manualmente os mesmos embeddings para experimentação e prototipagem, ajudando você a começar. Não é recomendado para uso em produção. Invocar seus próprios modelos localmente para gerar embeddings ou usar a API paga também pode ser feito usando uma abordagem semelhante.</p><p>Na função abaixo <code>GetTextEmbeddingForQuery</code> usamos a API de inferência em nossa string de consulta para gerar o vetor retornado de uma solicitação <code>POST</code> ao endpoint:</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>O vetor resultante, do tipo <code>[]float32</code> é então passado como <code>QueryVector</code> em vez de usar a opção <code>QueryVectorBuilder</code> para aproveitar o modelo previamente carregado no 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>Note que as opções <code>K</code> e <code>NumCandidates</code> permanecem as mesmas, independentemente das duas opções, e que os mesmos resultados são gerados, pois estamos usando o mesmo modelo para gerar os embeddings.</p><h2>Conclusão</h2><p>Aqui discutimos como realizar uma busca vetorial no Elasticsearch usando o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>. Confira o <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">repositório do GitHub</a> para acessar todo o código desta série. Continue para a <a href="https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client">parte 3</a> para obter uma visão geral da combinação da pesquisa vetorial com os recursos de pesquisa por palavra-chave abordados na <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">parte 1</a> em Go.</p><p>Até lá, boa caçada aos esquilos!</p><h2>Recursos</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Guia do Elasticsearch</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Cliente Go do Elasticsearch</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">O que é busca vetorial? | Elástico</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[Banco de dados vetorial]]></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[Execute consultas de texto com o cliente Elasticsearch Go.]]></title>
    <description><![CDATA[Aprenda como realizar consultas de texto tradicionais no Elasticsearch usando o cliente Elasticsearch Go por meio de um exemplo prático.]]></description>
    <content:encoded><![CDATA[<p>Desenvolver software em qualquer linguagem de programação, incluindo Go, é comprometer-se com uma vida inteira de aprendizado. Ao longo de sua trajetória universitária e profissional, Carly precisou se adaptar a ser poliglota e experimentar diversas linguagens de programação, incluindo Python, C, JavaScript, TypeScript e Java. Mas isso não foi suficiente! Recentemente, ela também começou a jogar Go!</p><p>Assim como os animais, as linguagens de programação e um de seus autores favoritos, a busca passou por uma evolução de diferentes práticas, o que pode dificultar a escolha da melhor opção para o seu caso específico. Neste blog, compartilharemos uma visão geral da pesquisa tradicional por palavras-chave, juntamente com <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">um exemplo</a> usando <a href="https://www.elastic.co/elasticsearch/">o Elasticsearch</a> e o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>.</p><h2>Pré-requisitos</h2><p>Para dar continuidade a este exemplo, certifique-se de que os seguintes pré-requisitos sejam atendidos:</p><ol><li><p>Instalação do Go versão 1.21 ou posterior</p></li><li><p>Crie seu próprio repositório Go usando a estrutura recomendada e o gerenciamento de pacotes abordados na <a href="https://go.dev/doc/code">documentação do Go.</a></p></li><li><p>Criação do seu próprio cluster Elasticsearch, preenchido com um conjunto de <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">páginas baseadas em roedores,</a> incluindo para o nosso amigável <a href="https://en.wikipedia.org/wiki/Gopher">Gopher</a>, da Wikipédia:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="Página do Gopher na Wikipédia" /><h2>Conectando-se ao Elasticsearch</h2><p>Em nossos exemplos, utilizaremos a <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">API tipada</a> oferecida pelo cliente Go. Para estabelecer uma conexão segura para qualquer consulta, é necessário configurar o cliente usando um dos seguintes métodos:</p><ol><li><p>ID da nuvem e chave de API, caso esteja utilizando o Elastic Cloud.</p></li><li><p>URL do cluster, nome de usuário, senha e certificado.</p></li></ol><p>A conexão com nosso cluster localizado no Elastic Cloud seria feita da seguinte forma:</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>A conexão <code>client</code> pode então ser usada para pesquisa, como mostrado mais adiante.</p><h2>Pesquisa por palavra-chave</h2><p>A busca por palavras-chave é o tipo de busca fundamental com o qual estamos familiarizados desde a criação do <a href="https://en.wikipedia.org/wiki/Archie_(search_engine)">Archie</a>, o primeiro mecanismo de busca documentado na internet, escrito em 1990.</p><p>Um componente central da busca por palavras-chave é a tradução de documentos em um índice invertido. Assim como o índice encontrado no final de um livro didático, um índice invertido contém um mapeamento entre uma lista de palavras-chave e sua localização em cada documento. O diagrama abaixo mostra as principais etapas de geração do índice:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt366681a12027f14b/6a17e7aa1d1b831c2093e452/9cd7b2a60d9aa54facb37738b821bba6ca925830-1440x581.png" alt="Geração de Índice Invertido" /><p>Conforme mostrado acima, a geração de tokens no Elasticsearch compreende três etapas principais:</p><ol><li><p>Remoção de caracteres desnecessários através de zero ou mais <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html"><code>char_filters</code></a>. Em nosso exemplo, estamos removendo elementos HTML dentro do campo <code>body_content</code> através do filtro <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html"><code>html_strip</code></a> .</p></li><li><p>Separando os tokens do conteúdo com o<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html"> tokenizador</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html"><code>standard</code></a> , que irá separar por espaçamento e pontuação chave.</p></li><li><p>Remover tokens indesejados ou transformar tokens do fluxo de saída do tokenizador usando zero ou mais opções <code>filter</code> , como o<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html"> filtro de token</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html"><code>lowercase</code></a>ou stemmers como o<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html"> stemmer</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html"><code>snowball</code></a>para transformar tokens de volta à sua raiz de idioma.</p></li></ol><h2>Pesquisando no Elasticsearch com Go</h2><p>Ao realizar consultas com o cliente Go, especificamos o índice que desejamos pesquisar e passamos a consulta e outras opções, como no exemplo abaixo:</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>No exemplo acima, realizamos uma<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"> consulta</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"><code>match</code></a>padrão para encontrar qualquer documento em nosso índice que contenha a string especificada passada para nossa função. Observe que passamos um <a href="https://pkg.go.dev/context#Background">novo contexto vazio</a> para a execução da pesquisa por meio de <code>Do(context.Background())</code>. Além disso, quaisquer erros retornados pelo Elasticsearch são enviados para o atributo <code>err</code> para registro e tratamento de erros.</p><p>Os resultados são retornados em <code>res.Hits.Hits</code> com o atributo <code>_Source</code> contendo o próprio documento em formato JSON. Para converter essa fonte em uma estrutura compatível com Go, precisamos <a href="https://pkg.go.dev/encoding/json#Unmarshal">desserializar</a> a resposta JSON usando o <a href="https://pkg.go.dev/encoding/json">pacote `encoding/json`</a> do Go, como mostrado no exemplo abaixo:</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>A busca e a desserialização da consulta <code>gopher</code> retornarão a página da Wikipédia sobre Gopher, como esperado:</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher}
]
<p>No entanto, se consultarmos <code>What do Gophers eat?</code> , não obtemos exatamente os resultados que desejamos:</p>[]
<p>Uma simples busca por palavra-chave permite que os resultados sejam retornados ao seu aplicativo Go de forma eficiente e com a qual já estamos familiarizados a partir dos aplicativos que utilizamos. Também funciona muito bem para correspondências exatas de termos relevantes para cenários como a busca por uma empresa ou termo específico.</p><p>No entanto, como podemos ver acima, ele tem dificuldades em identificar o contexto e a semântica devido ao problema de incompatibilidade de vocabulário. Além disso, o suporte para formatos de arquivo não textuais, como imagens e áudio, é um desafio.</p><h2>Conclusão</h2><p>Aqui discutimos como realizar consultas de texto tradicionais no Elasticsearch usando o <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">cliente Elasticsearch Go</a>. Dado que o Go é amplamente utilizado para scripts de infraestrutura e construção de servidores web, é útil saber como pesquisar em Go.</p><p>Confira o <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">repositório do GitHub</a> para acessar todo o código desta série. Continue para a <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">parte 2</a> para obter uma visão geral da pesquisa vetorial e como realizar pesquisas vetoriais em Go. Até lá, boa caçada aos esquilos!</p><h2>Recursos</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Guia do Elasticsearch</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Cliente Go do Elasticsearch</a></p></li><li><p><a href="https://codingexplained.com/coding/elasticsearch/understanding-analysis-in-elasticsearch-analyzers">Entendendo a Análise no Elasticsearch (Analisadores) por 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>