<?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[Laurent Saint-Félix - 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[Laurent Saint-Félix - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/kr/search-labs/author/laurent-saint-felix</link>
    </image>
    <link>https://www.elastic.co/kr/search-labs/author/laurent-saint-felix</link>
    <atom:link href="https://www.elastic.co/kr/search-labs/rss/author/laurent-saint-felix.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[kr]]></language>
    <lastBuildDate>Fri, 16 Oct 2026 23:21:50 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Google MCP Toolbox for Databases, 새롭게 추가된 Elasticsearch 지원]]></title>
    <description><![CDATA[이제 Google MCP Toolbox for Databases에서 Elasticsearch 지원이 추가되었습니다. ES|QL 도구를 활용해 인덱스를 다양한 MCP 클라이언트와 안전하게 통합해 보세요.]]></description>
    <content:encoded><![CDATA[<p>이 글에서는 <a href="https://github.com/elastic/elasticsearch">Elasticsearch</a>와 Google MCP Toolbox를 함께 사용해 Elasticsearch 인덱스에서 정보를 추출하는 간단한 도구를 만드는 방법을 단계별로 살펴봅니다.</p><p>최근 Elastic은 <a href="https://github.com/googleapis/genai-toolbox">Google MCP Toolbox for Databases</a> 오픈소스 프로젝트에 Elasticsearch를 데이터베이스로 사용할 수 있는 지원 기능을 추가했습니다.</p><p>이 새로운 기능을 통해 Google MCP Toolbox로 Elasticsearch에 연결하고 데이터와 직접 "대화하듯" 상호작용할 수 있습니다.</p><h2>Elasticsearch</h2><p>Elasticsearch 인스턴스가 실행 중이어야 합니다. <a href="https://www.elastic.co/cloud">Elastic Cloud</a>에서 무료 체험을 활성화하거나 <a href="https://github.com/elastic/start-local">start-local</a> 스크립트를 사용해 로컬에 설치할 수 있습니다.</p>curl -fsSL https://elastic.co/start-local | sh<p>이 명령을 실행하면 컴퓨터에 Elasticsearch와 Kibana가 설치되고 Google MCP Toolbox 설정에 사용할 API 키가 생성됩니다.</p><p>API 키는 이전 명령의 출력 결과로 표시되며 elastic-start-local 폴더 내 .env 파일에 저장됩니다.</p><h2>예제 데이터 세트 설치하기</h2><p>설치가 완료되면 사용자 이름 <em>elastic</em>과 start-local 스크립트로 생성된 비밀번호(.env 파일에 저장됨)를 사용해 Kibana에 로그인할 수 있습니다.</p><p>Kibana에서 제공되는 <strong>eCommerce orders</strong> 데이터 세트를 설치할 수 있습니다. 이 데이터 세트에는 <strong>kibana_sample_data_ecommerce</strong>라는 단일 인덱스가 포함되어 있으며 전자상거래 웹사이트의 4,675개 주문 정보를 담고 있습니다. 각 주문에는 다음과 같은 정보가 포함되어 있습니다.</p><ul><li><p>고객 정보(이름, ID, 생년월일, 이메일 등)</p></li><li><p>주문 날짜</p></li><li><p>주문 ID</p></li><li><p>제품(가격, 수량, ID, 카테고리, 할인 등을 포함한 전체 제품 목록)</p></li><li><p>SKU</p></li><li><p>총액(세전, 세후)</p></li><li><p>총 수량</p></li><li><p>지리 정보(도시, 국가, 대륙, 위치, 지역)</p></li></ul><p>샘플 데이터를 설치하려면 Kibana의 <strong>통합</strong> 페이지를 열고(상단 검색창에서 "통합"을 검색) "Sample Data"를 설치하세요. 자세한 내용은 다음 문서에서 확인할 수 있습니다: <a href="https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana">https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana</a></p><p>이 글의 목표는 Google MCP Toolbox를 설정해 Elasticsearch에 연결하고 자연어로 <strong>kibana_sample_data_ecommerce</strong> 인덱스와 손쉽게 상호작용하는 방법을 보여주는 것입니다.</p><h2>Google MCP Toolbox</h2><p>Google MCP Toolbox는 애플리케이션과 AI 에이전트가 데이터베이스와 안전하고 효율적으로 상호작용할 수 있도록 설계된 오픈 소스 MCP 서버입니다. 이전에는 'GenAI Toolbox for Databases'로 알려졌으나 <a href="https://www.anthropic.com/news/model-context-protocol">Model Context Protocol</a>(MCP)을 전면 지원하게 되면서 현재의 이름으로 변경되었습니다. 이 프로젝트의 목적은 연결 풀링, 인증, 통합 가시성 등과 같은 다양한 운영 관리 요소들을 백그라운드에서 처리하여 에이전트를 데이터베이스에 연결할 때 기존에 필요하던 번거로운 작업을 줄이는 데 있습니다.</p><p>Toolbox의 핵심은 개발자가 데이터베이스 상호작용을 캡슐화한 재사용 가능한 고수준 도구를 정의할 수 있도록 한다는 점입니다. 이러한 도구는 MCP 호환 클라이언트(예: AI 에이전트)에서 호출할 수 있으며 클라이언트가 저수준 SQL 쿼리를 구현하거나 데이터베이스 연결을 직접 관리할 필요가 없습니다. 이러한 접근 방식은 데이터베이스 인식 에이전트를 구축하는 데 필요한 보일러플레이트 코드(boilerplate code)의 양을 크게 줄여 단 몇 줄의 애플리케이션 로직만으로도 고급 데이터 처리 기능을 통합할 수 있게 합니다. 한 번 정의된 도구는 여러 에이전트, 프레임워크, 언어 간에 손쉽게 공유할 수도 있습니다(그림 1).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte90070297ee83546/6a16fa29964cea694b08b972/137cea290bb70ad5da21853f9a6358cef4cf7451-1248x1056.png" alt="" /><p>Toolbox를 사용할 때의 큰 장점 중 하나는 기본으로 제공되는 보안 모델입니다. OAuth2와 OIDC 같은 인증 흐름을 기본적으로 지원하므로 개발자는 에이전트에서 민감한 데이터베이스 자격 증명을 직접 다루거나 저장하지 않아도 됩니다. 또한 이 플랫폼은 OpenTelemetry를 통해 메트릭과 트레이싱을 포함한 통합 가시성 기능을 제공하며 이는 디버깅, 모니터링 및 프로덕션 배포에 필수적입니다. 종합하면 MCP Toolbox는 MCP를 지원하는 모든 시스템에서 데이터와 상호작용하기 위한 통합되고 안전하며 확장 가능한 인터페이스 역할을 합니다.</p><h2>MCP Toolbox 설치 방법</h2><p>다음 명령어를 사용하여 Linux에서 MCP Toolbox 서버를 설치할 수 있습니다.</p>export VERSION=0.21.0
curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox<p>macOS 또는 Windows에 설치하려면 <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/#installing-the-server">여기</a>에 있는 자세한 안내를 따르세요.</p><h2>Toolbox를 Elasticsearch용으로 구성하기</h2><p>Elasticsearch용 MCP Toolbox를 구성하려면 다음과 같이 <strong>tools.yaml</strong> 파일을 생성해야 합니다.</p>sources:
  my-cluster:
    kind: elasticsearch
    addresses:
      - http://localhost:9200
    apikey: &lt;insert-here-api-key&gt;

tools:
  customer-orders:
    kind: elasticsearch-esql
    source: my-cluster
    description: Get the orders made by a customer identified by name.
    query: |
    	FROM kibana_sample_data_ecommerce | WHERE MATCH(customer_full_name, ?name, {"operator": "AND"})
    parameters:
      - name: name
        type: string
        description: The customer name.

toolsets:
  elasticsearch-tools:
    - customer-orders<p><strong>&lt;insert-here-api-key&gt;</strong> 값을 유효한 Elasticsearch API 키로 교체해야 합니다. 로컬에서 start-local로 Elasticsearch를 실행하고 있는 경우 생성된 .env 파일의 <strong>ES_LOCAL_API_KEY</strong> 변수에서 API 키를 확인할 수 있습니다. Elastic Cloud를 사용하는 경우 <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys">여기</a>에 설명된 절차를 따라 API 키를 생성할 수 있습니다.</p><p>이전 도구에는 Elasticsearch를 위한 다음 ES|QL 쿼리가 포함되어 있습니다:</p><p>ES|QL에 익숙하지 않다면 간단히 이렇게 이해할 수 있습니다. ES|QL은 Elastic이 개발한 쿼리 언어로 SQL과 비슷한 방식으로 하나 이상의 인덱스를 대상으로 데이터를 검색할 수 있습니다. ES|QL에 대한 더 자세한 내용은 <a href="https://www.elastic.co/docs/reference/query-languages/esql">여기</a>에서 공식 문서를 통해 확인할 수 있습니다.</p><p>위의 쿼리는 <strong>?name</strong> 매개변수(물음표는 매개변수를 의미)를 사용해 지정된 고객 이름이 포함된 모든 주문을 <strong>kibana_sample_data_ecommerce</strong> 인덱스에서 검색합니다.</p><p>고객 이름은 앞서 작성한 YAML 구성에서 string 타입과 'The customer name' 설명으로 정의되었습니다.</p><p>이 도구를 사용하면 <em>고객인 Foo는 2025년 10월에 몇 건의 주문을 했나요?</em>와 같은 고객의 주문 관련 질문에 답할 수 있습니다.</p><p>도구와 그 매개변수에 대한 설명은 사용자의 자연어 요청에서 관련 정보를 추출하는 데 매우 중요합니다. 이러한 정보 추출은 대규모 언어 모델(LLM)의 <strong>함수 호출</strong> 기능을 통해 수행됩니다. 실제로 LLM은 필요한 정보를 얻기 위해 실행해야 할 함수(도구)와 해당 함수에 필요한 매개변수를 자동으로 식별할 수 있습니다.</p><p>함수 호출에 대한 자세한 내용은 Ashish Tiwari가 작성한 <a href="https://www.elastic.co/search-labs/blog/function-calling-with-elastic">OpenAI function calling with Elasticsearch(Elasticsearch와 함께 사용하는 OpenAI 함수 호출)</a>라는 글을 참고하세요.</p><h2>Toolbox 서버 실행하기</h2><p>앞서 작성한 tools.yaml 파일을 사용해 MCP Toolbox를 다음 명령어로 실행할 수 있습니다.</p>./toolbox --tools-file tools.yaml --ui<p><strong> -ui</strong> 매개변수를 사용하면 <a href="http://127.0.0.1:5000/ui">http://127.0.0.1:5000/ui</a>에서 웹 애플리케이션이 실행됩니다(그림 2).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0fb3953fae603572/6a16fa2aa6c2b92763e794fb/3caf2339b632bafd5847af1ed8b33b518a25b8a2-1600x314.png" alt="" /><p><strong>Tools</strong> &gt; <strong>customer-orders</strong>를 선택한 뒤 <strong>name</strong> 매개변수에 고객 이름(예: Gwen Sanders)을 입력하고 <strong>Run Tool</strong> 버튼을 클릭할 수 있습니다. 그림 3에 표시된 것과 같은 JSON 응답이 표시됩니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltca02df8c78cb39ff/6a16fa2c961e6909b5c4cd22/b167e0142afb8919d9cedf6d0fa431d33d0e55f8-1600x933.png" alt="" /><p>이로써 설정이 완료되며 MCP Toolbox는 <strong>customer-orders</strong> 도구를 실행해 Elasticsearch와 통신하고 ES|QL 쿼리를 실행할 수 있습니다.</p><h2>Gemini CLI와 함께 MCP Toolbox 사용하기</h2><p>데이터베이스용 MCP Toolbox와의 통신에는 어떤 MCP 클라이언트든 사용할 수 있습니다. 예를 들어 Gemini를 사용하기 위한 명령줄 도구인 <a href="https://github.com/google-gemini/gemini-cli">Gemini CLI</a>를 사용할 수 있습니다. Gemini CLI는 <a href="https://geminicli.com/docs/get-started/installation/">여기</a>에 안내된 지침에 따라 설치할 수 있습니다.</p><p>Gemini CLI에는 MCP Toolbox용으로 사전 구성된 확장 프로그램이 제공되며 <a href="https://github.com/gemini-cli-extensions/mcp-toolbox">gemini-cli-extensions/mcp-toolbox</a>에서 사용할 수 있습니다. 다음 명령어를 실행해 이 확장 프로그램을 설치할 수 있습니다.</p>gemini extensions install https://github.com/gemini-cli-extensions/mcp-toolbox<p>설치가 완료되면 MCP Toolbox용 tools.yaml 설정 파일을 저장한 디렉터리로 이동한 뒤 다음과 같이 Gemini CLI를 실행해야 합니다. 이는 Gemini CLI가 MCP Toolbox와 자동으로 구성되기 위해 필요한 단계입니다.</p>gemini<p>그림 4에 표시된 출력 결과를 확인할 수 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf7245c10b9e32cd6/6a16fa2d964cea073208b976/0f22df6d3da13c1dc50dcb560414fa7c630eb9a7-1434x341.png" alt="" /><p>다음 명령어로 MCP Toolbox가 연결되어 있는지 확인할 수 있습니다.</p>/mcp list<p><strong>mcp_toolbox</strong> 항목 아래에 <strong>customer-orders</strong> 도구가 나열된 것을 확인할 수 있습니다(그림 5).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte857b42dbe604203/6a16fa2f8b73cb531b189e33/97edbc40de9e44f469f6f3a09427532be167de0e-493x155.png" alt="" /><p>MCP Toolbox가 Gemini CLI에 연결되었다면 이제 ”<em>고객인 Gwen Sanders의 주문 내역을 알려주세요</em>”와 같은 질문을 해볼 수 있습니다. 그러면 Gemini CLI가 mcp_toolbox 서버에서 customer-orders 도구를 실행할 수 있는 권한을 요청합니다(그림 6 참조).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb7ea752c1a39da7/6a16fa30cdacbfdf937d27ff/c052f3b5e49436903b804280c0065f67ee02444b-1432x284.png" alt="" /><p>확인되면 Gemini CLI는 MCP Toolbox에 요청을 보내 JSON 응답을 받은 다음 이를 바탕으로 최종 응답을 구성합니다(그림 7).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb9f6e04987137a9f/6a16fa320811ae2297e9fef7/7ea5128f1705951c2757af6da4b456d394d4a080-1432x734.png" alt="" /><p>Gemini CLI의 응답에는 Gwen Sanders가 2개 상품을 한 번만 주문했으며 총액은 132유로라는 내용이 표시됩니다.</p><h2>MCP Toolbox SDKs</h2><p>Google MCP Toolbox는 Go, Python, JavaScript로 작성된 프로그램에서 모든 기능에 접근할 수 있는 SDK도 제공합니다.</p><p>예를 들어 Python SDK는 다음의 GitHub 페이지에서 이용할 수 있습니다: <a href="https://github.com/googleapis/mcp-toolbox-sdk-python">https://github.com/googleapis/mcp-toolbox-sdk-python</a></p><p>MCP Toolbox에 연결하기 위해 간단한 에이전트를 만들어야 합니다. 이를 위해 다음 패키지를 설치해야 합니다.</p>pip install toolbox-core
pip install google-adk<p>그리고 아래 명령어로 새로운 에이전트 프로젝트를 생성합니다.</p>adk create my_agent<p>이 명령을 실행하면 <strong>agent.py</strong> 파일이 포함된 <strong>my_agent</strong>라는 새 디렉터리가 생성됩니다.</p><p>Toolbox에 연결하기 위해 <strong>my_agent/agent.py</strong>를 다음 내용으로 업데이트합니다.</p>from google.adk import Agent
from google.adk.apps import App
from toolbox_core import ToolboxSyncClient

client = ToolboxSyncClient("http://127.0.0.1:5000")

root_agent = Agent(
    name='root_agent',
    model='gemini-2.5-flash',
    instruction="You are a helpful AI assistant designed to search information about a dataset of ecommerce orders.",
    tools=client.load_toolset(),
)

app = App(root_agent=root_agent, name="my_agent")<p>Google API 키를 포함한 <strong>.env</strong> 파일을 생성합니다.</p>echo 'GOOGLE_API_KEY="YOUR_API_KEY"' &gt; my_agent/.env<p>마지막으로 에이전트를 실행하여 결과를 확인할 수 있습니다. 에이전트를 실행하려면 아래 명령어를 입력합니다.</p>adk run my_agent<p>또는 웹 인터페이스로 제공할 수도 있습니다.</p>adk web --port 8000<p>두 경우 모두 Q&amp;A 인터페이스를 통해 MCP Toolbox와 상호작용할 수 있습니다. 예를 들어 이전 예시처럼 <em>고객인 Gwen Sanders의 주문 내역을 보여주세요</em>라고 질문할 수 있습니다.</p><p>다양한 SDK에 대한 자세한 내용은 <a href="https://googleapis.github.io/genai-toolbox/sdks/">이 문서 페이지</a>를 참고하세요.</p><h2>결론</h2><p>이번 글에서는 Google MCP Toolbox for Databases와 Elasticsearch를 통합하는 방법을 시연했습니다. 간단한 YAML 구성 파일만으로 ES|QL 언어를 활용해 자연어 질문을 Elasticsearch 쿼리로 변환하는 도구 세트를 정의할 수 있습니다.</p><p>또한 전자상거래 웹사이트의 주문 데이터를 포함하고 있는 kibana_sample_data_ecommerce 데이터 세트와 상호작용하는 방법을 시연했습니다. 이 설정 파일을 사용하면 MCP Toolbox 서버를 간단히 실행하고 모든 MCP 클라이언트에서 해당 서버에 연결할 수 있습니다.</p><p>마지막으로 Gemini CLI를 클라이언트로 사용해 MCP Toolbox for Databases에 연결하고 Elasticsearch에 저장된 전자상거래 데이터를 조회하는 과정을 시연했습니다. 특정 고객 이름을 기준으로 주문 정보를 조회하는 자연어 쿼리도 직접 실행해 보았습니다.</p><p>MCP 생태계가 계속 성장함에 따라 안전하고 프로덕션 환경에 바로 투입할 수 있는 인프라를 기반으로 한 경량 도구 정의 방식은 적은 노력으로도 점점 더 고도화되고 데이터에 정통한 에이전트를 구축할 수 있는 새로운 기회를 열어 줍니다. 로컬 환경에서 Elastic의 샘플 데이터 세트로 실험하는 경우나 대규모 애플리케이션에 검색 기능을 통합하는 경우에도 MCP Toolbox는 자연어를 통해 Elasticsearch 데이터와 상호작용할 수 있는 신뢰성 높고 확장 가능한 기반을 제공합니다.</p><p>에이전틱 AI 애플리케이션 개발에 대해 더 알고 싶다면 Anish Mathur와 Dana Juratoni가 작성한 <a href="https://search-labs-redesign.vercel.app/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Building AI Agentic Workflows with Elasticsearch(Elasticsearch로 AI 에이전틱 워크플로우 구축하기)</a>라는 글을 참고해 보세요.</p><p>Google MCP Toolbox 관련 추가 정보는 <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/">https://googleapis.github.io/genai-toolbox/getting-started/introduction/</a>에서 확인할 수 있습니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[에이전틱 AI]]></category>
    <dc:creator><![CDATA[Enrico Zimuel,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt72d49893c51407cf/6a16fa33cf4f2502bab2cf7e/425a48691f436ed47c9bdfaf5d561ac122b2c472-1062x668.png" length="0" type="image/png"/>
    <pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch와 Go로 고퍼 헌팅을 위한 하이브리드 검색 사용]]></title>
    <description><![CDATA[Elasticsearch와 Elasticsearch Go 클라이언트를 사용해 키워드 검색과 벡터 검색을 결합하여 하이브리드 검색을 수행하는 방법을 알아보세요.]]></description>
    <content:encoded><![CDATA[<p>이 시리즈의 이전 파트에서는 <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">기존 키워드 검색과</a> <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">벡터 검색에</a> Elasticsearch Go 클라이언트를 사용하는 방법을 보여드렸습니다. 세 번째 파트에서는 하이브리드 검색을 다룹니다. <a href="https://www.elastic.co/elasticsearch/">Elasticsearch와 Elasticsearch</a> <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Go 클라이언트를</a> 사용해 벡터 검색과 키워드 검색을 모두 결합하는 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">방법에 대한 예를</a> 공유해드리겠습니다.</p><h2>필수 구성 요소</h2><p>이 시리즈의 1부와 마찬가지로 이 예제에도 다음과 같은 전제 조건이 필요합니다:</p><ol><li><p>Go 버전 1.21 이상 설치</p></li><li><p><a href="https://go.dev/doc/code">Go 문서에서</a>다루는 권장 구조와 패키지 관리를 사용하여 자신만의 Go 리포지토리를 만드세요.</p></li><li><p>위키피디아에서 친숙한 Gopher를 포함해 설치류 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">기반</a> <a href="https://en.wikipedia.org/wiki/Gopher">페이지 세트로</a> 채워진 자체 Elasticsearch 클러스터를 생성합니다:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="위키피디아 고퍼 페이지" /><h2>Elasticsearch에 연결</h2><p>다시 한 번 말씀드리지만, 이 예제에서는 Go 클라이언트에서 제공하는 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API를</a> 사용하겠습니다. 쿼리에 대한 보안 연결을 설정하려면 다음 중 하나를 사용하여 클라이언트를 구성해야 합니다:</p><ol><li><p>Elastic Cloud를 사용하는 경우 클라우드 ID 및 API 키</p></li><li><p>클러스터 URL, 사용자 이름, 비밀번호 및 인증서</p></li></ol><p>Elastic Cloud에 위치한 클러스터에 연결하면 다음과 같이 됩니다:</p>func GetElasticsearchClient() (*elasticsearch.TypedClient, error) {
	var cloudID = os.Getenv("ELASTIC_CLOUD_ID")
	var apiKey = os.Getenv("ELASTIC_API_KEY")

	var es, err = elasticsearch.NewTypedClient(elasticsearch.Config{
		CloudID: cloudID,
		APIKey:  apiKey,
		Logger:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

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

	return es, nil
}
<p>그러면 다음 섹션에서 설명하는 것처럼 <code>client</code> 연결을 검색에 사용할 수 있습니다.</p><h2>하이브리드 검색을 위한 수동 부스팅</h2><p>검색 알고리즘 세트를 결합할 때 기존 방식은 각 쿼리 유형을 강화하기 위해 상수를 수동으로 구성하는 것이었습니다. 구체적으로, 각 쿼리에 대해 요인을 지정하고 결합된 결과 집합을 예상 집합과 비교하여 쿼리의 리콜을 결정합니다. 그런 다음 여러 요소 집합에 대해 반복하여 원하는 상태에 가장 가까운 요소를 선택합니다.</p><p>예를 들어, 아래 예시와 같이 <code>0.8</code> 계수가 부스트된 단일 텍스트 검색 쿼리와 <code>0.2</code> 계수가 낮은 knn 쿼리를 결합하려면 두 쿼리 유형에 모두 <code>Boost</code> 필드를 지정하면 됩니다:</p>func HybridSearchWithBoost(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	var k = 10
	var numCandidates = 10
	var knnBoost float32 = 0.2
	var queryBoost float32 = 0.8

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

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<p>각 쿼리에 대해 <code>Boost</code> 옵션에 지정된 요소가 문서 점수에 추가됩니다. 검색 쿼리의 점수를 knn 쿼리보다 더 큰 폭으로 높이면 키워드 쿼리의 결과에 더 많은 가중치가 부여됩니다.</p><p>특히 검색 전문가가 아닌 경우 수동 부스팅의 어려움은 원하는 결과 집합으로 이어지는 요소를 파악하기 위해 튜닝이 필요하다는 점입니다. 원하는 결과 집합에 가장 근접한 값이 무엇인지 확인하기 위해 임의의 값을 시도해 보는 것입니다.</p><h2>하이브리드 검색의 상호 순위 퓨전 &amp; Go 클라이언트</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">상호 순위 퓨전</a>(RRF)은 Elasticsearch 8.9의 하이브리드 검색을 위한 기술 미리보기로 출시되었습니다. 튜닝과 관련된 학습 곡선을 줄이고 결과 집합을 최적화하기 위해 요소를 실험하는 시간을 줄이는 것을 목표로 합니다.</p><p>RRF를 사용하면 아래 알고리즘에 따라 점수를 혼합하여 문서 점수를 다시 계산합니다:</p>score := 0.0
// q is a query in the set of queries (vector and keyword search)
for _, q := range queries {
    // result(q) is the results 
    if document in result(q) {
        // k is a ranking constant (default 60)
        // rank(result(q), d) is the document's rank within result(q) 
        // range from 1 to the window_size (default 100)
        score +=  1.0 / (k + rank(result(q), d))
    }
}

return score
<p>RRF 사용의 장점은 Elasticsearch 내에서 합리적인 기본값을 사용할 수 있다는 것입니다. 순위 상수 <code>k</code> 기본값은 <code>60</code> 입니다. 대규모 데이터 집합을 검색할 때 반환된 문서의 관련성과 쿼리 성능 간의 균형을 맞추기 위해 고려되는 각 쿼리에 대한 결과 집합의 크기는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html#rrf-api">문서에</a> 설명된 대로 기본값이 <code>100</code> 인 <code>window_size</code> 의 값으로 제한됩니다.</p><p><code>k</code> 및 <code>windows_size</code> 는 아래 예시와 같이 Go 클라이언트의 <code>Rank</code> 메소드 내 <code>Rrf</code> 설정에서도 구성할 수 있습니다:</p>func HybridSearchWithRRF(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	var k = 10
	var numCandidates = 10

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

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

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<h2>결론</h2><p>여기서는 Elasticsearch <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Go 클라이언트를 사용하여 Elasticsearch에서 벡터 검색과 키워드 검색을 결합하는</a> 방법에 대해 설명했습니다.</p><p>이 시리즈의 모든 코드는 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub 리포지토리에서</a> 확인하세요. 아직 읽어보지 않았다면 이 시리즈의 모든 코드를 <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">파트 1과</a> <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">파트 2에서</a> 확인하세요.</p><p><em>즐거운 고퍼 사냥 되세요!</em></p><h2>리소스</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch 가이드</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go 클라이언트</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">벡터 검색이란 무엇인가요? | Elastic</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html">상호 등급 융합</a></p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client</guid>
    <category><![CDATA[벡터 데이터베이스]]></category>
    <category><![CDATA[Go]]></category>
    <dc:creator><![CDATA[Carly Richmond,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcae959696d55a9b/6a1704d5ab7f085a56db9d7c/491ef9efbb30b253e1d9e3b7f816a9a23c8f5264-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 02 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch Go 클라이언트로 Elasticsearch에서 벡터 검색 수행]]></title>
    <description><![CDATA[실제 예제를 통해 Elasticsearch Go 클라이언트를 사용하여 Elasticsearch에서 벡터 검색을 수행하는 방법을 알아보세요.]]></description>
    <content:encoded><![CDATA[<p>Go를 포함한 모든 프로그래밍 언어로 소프트웨어를 구축하는 것은 평생에 걸친 학습에 전념하는 것입니다. 대학과 직장 경력을 통해 Carly는 벡터 검색의 최신 및 최고의 구현을 포함하여 많은 프로그래밍 언어와 기술을 다뤄왔습니다. 하지만 그것만으로는 충분하지 않았습니다! 그래서 최근에 칼리도 바둑을 시작했습니다.</p><p>동물, 프로그래밍 언어, 친근한 작가와 마찬가지로 검색도 검색 사용 사례에 따라 결정하기 어려울 정도로 다양한 방식으로 진화해 왔습니다. 이 블로그에서는 벡터 검색에 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">대한 개요와</a> <a href="https://www.elastic.co/elasticsearch/">함께 Elasticsearch와</a> <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go 클라이언트를</a> 사용한 각 접근 방식의 예를 공유하겠습니다. 이 예제에서는 Elasticsearch와 Go에서 벡터 검색을 사용해 고퍼를 찾고 고퍼가 무엇을 먹는지 알아내는 방법을 보여드립니다.</p><h2>필수 구성 요소</h2><p>이 예제를 따라 하려면 다음 전제 조건이 충족되는지 확인하세요:</p><ol><li><p>Go 버전 1.21 이상 설치</p></li><li><p>를 사용하여 나만의 Go 리포지토리를 생성합니다.</p></li><li><p>위키피디아에서 친숙한 <a href="https://en.wikipedia.org/wiki/Gopher">Gopher를</a> 포함한 설치류 기반 페이지 세트로 채워진 자체 Elasticsearch 클러스터를 생성합니다:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="위키피디아 고퍼 페이지" /><h2>Elasticsearch에 연결</h2><p>이 예제에서는 Go 클라이언트에서 제공하는 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API를</a> 사용하겠습니다. 쿼리에 대한 보안 연결을 설정하려면 다음 중 하나를 사용하여 클라이언트를 구성해야 합니다:</p><ol><li><p>Elastic Cloud를 사용하는 경우 클라우드 ID와 API 키입니다.</p></li><li><p>클러스터 URL, 사용자 이름, 비밀번호 및 인증서를 입력합니다.</p></li></ol><p>Elastic Cloud에 위치한 클러스터에 연결하면 다음과 같이 됩니다:</p>func GetElasticsearchClient() (*elasticsearch.TypedClient, error) {
	var cloudID = os.Getenv("ELASTIC_CLOUD_ID")
	var apiKey = os.Getenv("ELASTIC_API_KEY")

	var es, err = elasticsearch.NewTypedClient(elasticsearch.Config{
		CloudID: cloudID,
		APIKey:  apiKey,
		Logger:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

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

	return es, nil
}
<p>그런 다음 다음 섹션에 표시된 것처럼 <code>client</code> 연결을 벡터 검색에 사용할 수 있습니다.</p><h2>벡터 검색</h2><p>벡터 검색은 벡터를 사용하여 검색 문제를 수학적 비교로 변환하여 이 문제를 해결하려고 시도합니다. 문서 임베딩 프로세스에는 모델을 사용하여 문서를 고밀도 벡터 표현 또는 단순히 숫자 스트림으로 변환하는 추가 단계가 있습니다. 이 접근 방식의 장점은 이미지나 오디오와 같은 텍스트가 아닌 문서를 쿼리와 함께 벡터로 변환하여 검색할 수 있다는 점입니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4b3b9b2ad1e8f46/6a1704d06234e0800fdb1927/b113358093e367358d684f7aaf0a6684ebb2d0dd-1440x653.png" alt="벡터 검색 다이어그램" /><p>간단히 말해서 벡터 검색은 벡터 거리 계산의 집합입니다. 아래 그림에서는 쿼리 <code>Go Gopher</code>의 벡터 표현을 벡터 공간의 문서와 비교하여 가장 가까운 결과(상수 <code>k</code> 로 표시됨)를 반환합니다:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c736ecfc49bb038/6a1704d2cf4f25bcb6b2d075/54a17a4b41029644e7c66f33d428e8d01a6f4ce3-1184x743.png" alt="Gopher 벡터 스페이스 예제" /><p>문서 임베딩을 생성하는 데 사용하는 접근 방식에 따라 고퍼가 무엇을 먹는지 알아내는 방법은 두 가지가 있습니다.</p><h3>접근 방식 1: 나만의 모델 가져오기</h3><p>플래티넘 라이선스를 사용하면 모델을 업로드하고 추론 API를 사용하여 Elasticsearch 내에서 임베딩을 생성할 수 있습니다. 모델을 설정하는 데는 6단계가 있습니다:</p><ol><li><p>모델 리포지토리에서 업로드할 PyTorch 모델을 선택합니다. 이 예제에서는 임베딩을 생성하기 위해 Hugging Face의 <a href="https://huggingface.co/sentence-transformers/msmarco-MiniLM-L-12-v3">문장 트랜스포머/msmarco-MiniLM-L-12-v3를</a> 사용하고 있습니다.</p></li><li><p>Elasticsearch 클러스터에 대한 자격 증명과 작업 유형 <code>text_embeddings</code> 을 사용하여 <a href="https://www.elastic.co/guide/en/elasticsearch/client/eland/current/overview.html">Python용 Eland Machine Learning 클라이언트를</a> 사용하여 모델을 Elastic에 로드합니다. Eland가 설치되어 있지 않은 경우 아래와 같이 <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-import-model.html#ml-nlp-import-docker">Docker를 사용하여 가져오기 단계를 실행할</a> 수 있습니다:</p></li></ol>docker run -it --rm --network host \
    docker.elastic.co/eland/eland \
    eland_import_hub_model \
      --cloud-id $ELASTIC_CLOUD_ID \
      --es-api-key $ELASTIC_API_KEY \
      --hub-model-id sentence-transformers/msmarco-MiniLM-L-12-v3 \
      --task-type text_embedding
<ol><li><p>업로드가 완료되면 샘플 문서로 <code>sentence-transformers__msmarco-minilm-l-12-v3</code> 모델을 빠르게 테스트하여 임베딩이 예상대로 생성되는지 확인합니다:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a399e1f50ecfdaf/6a1704d4ab7f08935edb9d78/fbbdde621361a487eb07304bed029c228d0f7aa6-1440x789.png" alt="Elastic Test 학습된 모델 예시" /><ol><li><p>추론 프로세서가 포함된 수집 파이프라인을 만듭니다. 이렇게 하면 업로드한 모델을 사용하여 벡터 표현을 생성할 수 있습니다:</p></li></ol>PUT _ingest/pipeline/search-rodents-vector-embedding-pipeline
{
  "processors": [
    {
      "inference": {
        "model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
        "target_field": "text_embedding",
        "field_map": {
          "body_content": "text_field"
        }
      }
    }
  ]
}
<ol><li><p>각 문서에 대해 생성된 벡터 임베딩을 저장하기 위해 <code>dense_vector</code> 유형의 <code>text_embedding.predicted_value</code> 필드를 포함하는 새 인덱스를 만듭니다:</p></li></ol>PUT vector-search-rodents
{
  "mappings": {
    "properties": {
      "text_embedding.predicted_value": {
        "type": "dense_vector",
        "dims": 384,
        "index": true,
        "similarity": "cosine"
      },
      "text": {
        "type": "text"
      }
    }
  }
}
<ol><li><p>새로 생성된 수집 파이프라인을 사용하여 문서를 재색인하여 각 문서에 추가 필드 <code>text_embedding.predicted_value</code> 로 텍스트 임베딩을 생성합니다:</p></li></ol>POST _reindex
{
  "source": {
    "index": "search-rodents"
  },
  "dest": {
    "index": "vector-search-rodents",
    "pipeline": "search-rodents-vector-embedding-pipeline"
  }
}
<p>이제 아래 예시와 같이 새 인덱스 <code>vector-search-rodents</code> 를 사용하여 동일한 검색 API에서 <code>Knn</code> 옵션을 사용할 수 있습니다:</p>func VectorSearch(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
  var k = 10
	var numCandidates = 10

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

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

	return getRodents(res.Hits.Hits)
}
<p>마샬링 해제를 통해 JSON 결과 객체를 변환하는 것은 키워드 검색 예제와 똑같은 방식으로 수행됩니다. 상수 <code>K</code> 및 <code>NumCandidates</code> 을 사용하여 반환할 이웃 문서의 수와 샤드당 고려할 후보의 수를 구성할 수 있습니다. 후보자 수를 늘리면 결과의 정확도는 높아지지만 더 많은 비교가 수행되므로 쿼리 실행 시간이 길어집니다.</p><p><code>What do Gophers eat?</code> 쿼리를 사용하여 코드를 실행하면 반환되는 결과는 아래와 유사하게 표시되며, 이전 키워드 검색과 달리 Gopher 문서에 요청된 정보가 포함되어 있음을 강조합니다:</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher} 
  {ID:64f74ed34acb3d71aed91fcd Title:Squirrel - Wikipedia Url:https://en.wikipedia.org/wiki/Squirrel} 
  //Other results omitted
]
<h3>접근 방식 2: 허깅 얼굴 추론 API</h3><p>또 다른 옵션은 Elasticsearch 외부에서 동일한 임베딩을 생성하여 문서의 일부로 수집하는 것입니다. 이 옵션은 Elasticsearch 머신 러닝 노드를 사용하지 않으므로 무료 티어에서 수행할 수 있습니다.</p><p>허깅 페이스는 무료로 사용할 수 있는 속도 제한이 없는 <a href="https://huggingface.co/docs/api-inference/index">추론 API를</a> 제공하며, 계정과 API 토큰을 사용하면 실험 및 프로토타이핑을 위해 동일한 임베딩을 수동으로 생성하여 시작할 수 있습니다. 프로덕션용으로는 권장하지 않습니다. 로컬에서 자체 모델을 호출하여 임베딩을 생성하거나 유료 API를 사용하는 것도 비슷한 방식으로 수행할 수 있습니다.</p><p>아래 함수 <code>GetTextEmbeddingForQuery</code> 에서는 쿼리 문자열에 대한 추론 API를 사용하여 <code>POST</code> 요청에서 엔드포인트로 반환된 벡터를 생성합니다:</p>// HuggingFace text embedding helper
func GetTextEmbeddingForQuery(term string) []float32 {
    // HTTP endpoint
    model := "sentence-transformers/msmarco-minilm-l-12-v3"
    posturl := fmt.Sprintf("https://api-inference.huggingface.co/pipeline/feature-extraction/%s", model)

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

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

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

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

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

    defer res.Body.Close()

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

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

    return post
}
<p>그런 다음 <code>[]float32</code> 유형의 결과 벡터가 <code>QueryVectorBuilder</code> 옵션을 사용하는 대신 <code>QueryVector</code> 으로 전달되어 이전에 Elastic에 업로드한 모델을 활용합니다.</p>func VectorSearchWithGeneratedQueryVector(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	vector, err := GetTextEmbeddingForQuery(term)
	if err != nil {
		return nil, err
	}

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

  var k = 10
	var numCandidates = 10

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

	if err != nil {
		return nil, err
	}

	return getRodents(res.Hits.Hits)
}
<p><code>K</code> 및 <code>NumCandidates</code> 옵션은 두 옵션에 관계없이 동일하게 유지되며 동일한 모델을 사용하여 임베딩을 생성하기 때문에 동일한 결과가 생성됩니다.</p><h2>결론</h2><p>여기서는 Elasticsearch <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Go 클라이언트를 사용하여 Elasticsearch에서 벡터 검색을 수행하는</a> 방법에 대해 설명했습니다. 이 시리즈의 모든 코드는 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">GitHub 리포지토리에서</a> 확인하세요. <a href="https://www.elastic.co/search-labs/blog/hybrid-search-with-the-elasticsearch-go-client">3부에서는</a> <a href="https://www.elastic.co/search-labs/blog/perform-text-queries-with-the-elasticsearch-go-client">1부에서</a> 다룬 벡터 검색과 키워드 검색 기능을 Go에서 결합하는 방법에 대한 개요를 살펴봅니다.</p><p>그때까지 고퍼 사냥을 즐기세요!</p><h2>리소스</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch 가이드</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go 클라이언트</a></p></li><li><p><a href="https://www.elastic.co/what-is/vector-search">벡터 검색이란 무엇인가요? | Elastic</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[벡터 데이터베이스]]></category>
    <category><![CDATA[Go]]></category>
    <dc:creator><![CDATA[Carly Richmond,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcae959696d55a9b/6a1704d5ab7f085a56db9d7c/491ef9efbb30b253e1d9e3b7f816a9a23c8f5264-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch Go 클라이언트로 텍스트 쿼리 수행]]></title>
    <description><![CDATA[실제 예제를 통해 Elasticsearch Go 클라이언트를 사용하여 Elasticsearch에서 기존 텍스트 쿼리를 수행하는 방법을 알아보세요.]]></description>
    <content:encoded><![CDATA[<p>Go를 포함한 모든 프로그래밍 언어로 소프트웨어를 구축하는 것은 평생에 걸친 학습에 전념하는 것입니다. 대학과 직장 생활을 하는 동안 Carly는 여러 언어를 구사하는 것에 적응해야 했고 Python, C, JavaScript, TypeScript, Java 등 다양한 프로그래밍 언어를 다뤄야 했습니다. 하지만 그것만으로는 충분하지 않았습니다! 그래서 최근에는 그녀도 바둑을 시작했습니다!</p><p>동물, 프로그래밍 언어, 친근한 저자 중 한 명처럼 검색도 검색 사용 사례에 따라 결정하기 어려울 정도로 다양한 방식으로 진화해 왔습니다. 이 블로그에서는 기존 키워드 검색에 대한 개요와 함께 <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a> <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">및 Elasticsearch</a> Go <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch">클라이언트를 사용한 예제를</a> 공유합니다.</p><h2>필수 구성 요소</h2><p>이 예제를 따라 하려면 다음 전제 조건이 충족되는지 확인하세요:</p><ol><li><p>Go 버전 1.21 이상 설치</p></li><li><p><a href="https://go.dev/doc/code">Go 문서에서</a>다루는 권장 구조와 패키지 관리를 사용하여 자신만의 Go 리포지토리를 만드세요.</p></li><li><p>위키피디아에서 친숙한 Gopher를 포함한 <a href="https://github.com/carlyrichmond/gopher-hunting-elasticsearch#sources">설치류 기반</a> <a href="https://en.wikipedia.org/wiki/Gopher">페이지 세트로</a> 채워진 자체 Elasticsearch 클러스터를 생성합니다:</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6a436c42996e5172/6a1704cf0c48573d1c01a957/34fa81a9b4c292634c719b8303a9b6b7506d7920-1440x662.png" alt="위키피디아 고퍼 페이지" /><h2>Elasticsearch에 연결</h2><p>이 예제에서는 Go 클라이언트에서 제공하는 <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/typedapi.html">Typed API를</a> 사용하겠습니다. 쿼리에 대한 보안 연결을 설정하려면 둘 중 하나를 사용하여 클라이언트를 구성해야 합니다:</p><ol><li><p>Elastic Cloud를 사용하는 경우 클라우드 ID와 API 키입니다.</p></li><li><p>클러스터 URL, 사용자 이름, 비밀번호 및 인증서를 입력합니다.</p></li></ol><p>Elastic Cloud에 위치한 클러스터에 연결하면 다음과 같이 됩니다:</p>func GetElasticsearchClient() (*elasticsearch.TypedClient, error) {
	var cloudID = os.Getenv("ELASTIC_CLOUD_ID")
	var apiKey = os.Getenv("ELASTIC_API_KEY")

	var es, err = elasticsearch.NewTypedClient(elasticsearch.Config{
		CloudID: cloudID,
		APIKey:  apiKey,
		Logger:  &amp;elastictransport.ColorLogger{os.Stdout, true, true},
	})

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

	return es, nil
}
<p>그러면 나중에 표시된 것처럼 <code>client</code> 연결을 검색에 사용할 수 있습니다.</p><h2>키워드 검색</h2><p>키워드 검색은 1990년 문서화된 최초의 인터넷 검색 엔진인 <a href="https://en.wikipedia.org/wiki/Archie_(search_engine)">Archie가</a> 처음 등장한 이래로 우리에게 익숙한 기본적인 검색 유형입니다.</p><p>키워드 검색의 핵심 구성 요소는 문서를 반전된 색인으로 변환하는 것입니다. 교과서 뒷면에 있는 색인과 마찬가지로, 반전된 색인에는 토큰 목록과 각 문서 내 토큰 위치 간의 매핑이 포함되어 있습니다. 아래 다이어그램은 인덱스 생성의 주요 단계를 보여줍니다:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt366681a12027f14b/6a17e7aa1d1b831c2093e452/9cd7b2a60d9aa54facb37738b821bba6ca925830-1440x581.png" alt="반전 인덱스 생성" /><p>위에 표시된 바와 같이, Elasticsearch에서 토큰 생성은 세 가지 주요 단계로 구성됩니다:</p><ol><li><p>0 개 이상을 통해 불필요한 문자 제거 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html"><code>char_filters</code></a>. 이 예에서는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html"><code>html_strip</code></a> 필터를 통해 <code>body_content</code> 필드 내의 HTML 요소를 제거합니다.</p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html"><code>standard</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html"> 토큰화</a> 도구로 콘텐츠에서 토큰을 분할하면 간격과 키 구두점에 따라 토큰이 분할됩니다.</p></li><li><p>원치 않는 토큰을 제거하거나 토큰을 언어 루트로 다시 변환하는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html"><code>lowercase</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html"> 토큰 필터</a> 또는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html"><code>snowball</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html"> 스템머와</a> 같은 0개 이상의 <code>filter</code> 옵션을 사용하여 토큰라이저의 출력 스트림에서 토큰을 변환합니다.</p></li></ol><h2>Go로 Elasticsearch에서 검색하기</h2><p>Go 클라이언트로 쿼리할 때는 아래 예시와 같이 검색할 인덱스를 지정하고 쿼리 및 기타 옵션을 전달합니다:</p>func KeywordSearch(client *elasticsearch.TypedClient, term string) ([]Rodent, error) {
	res, err := client.Search().
		Index("search-rodents").
		Query(&amp;types.Query{
			Match: map[string]types.MatchQuery{
				"title": {Query: term},
			},
		}).
		From(0).
		Size(10).
		Do(context.Background())

	if err != nil {
		return nil, fmt.Errorf("could not search for rodents: %w", err)
	}

	return getRodents(res.Hits.Hits)
}
<p>위의 예에서는 표준 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"><code>match</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html"> 쿼리를</a> 수행하여 인덱스에서 함수에 전달된 지정된 문자열이 포함된 문서를 찾습니다. <code>Do(context.Background())</code> 을 통해 검색 실행에 <a href="https://pkg.go.dev/context#Background">새로운 빈 컨텍스트를</a> 전달합니다. 또한, Elasticsearch에서 반환된 모든 오류는 로깅 및 오류 처리를 위해 <code>err</code> 속성으로 출력됩니다.</p><p>결과는 <code>_Source</code> 속성과 함께 문서 자체를 JSON 형식으로 포함하는 <code>res.Hits.Hits</code> 형식으로 반환됩니다. 이 소스를 Go 친화적인 구조체로 변환하려면 아래 예시와 같이 Go <a href="https://pkg.go.dev/encoding/json">encoding/json 패키지를</a> 사용하여 JSON 응답을 <a href="https://pkg.go.dev/encoding/json#Unmarshal">마샬링 해제해야 합니다:</a></p>func getRodents(hits []types.Hit) ([]Rodent, error) {
	var rodents []Rodent

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

		if err != nil {
			return nil, fmt.Errorf("an error occurred while unmarshaling rodent %s: %w", hit.Id_, err)
		}

		currentRodent.ID = hit.Id_
		rodents = append(rodents, currentRodent)
	}

	return rodents, nil
}
<p><code>gopher</code> 쿼리를 검색하고 마샬링을 해제하면 예상대로 Gopher의 Wikipedia 페이지가 반환됩니다:</p>[
  {ID:64f74ecd4acb3df024d91112 Title:Gopher - Wikipedia Url:https://en.wikipedia.org/wiki/Gopher}
]
<p>하지만 <code>What do Gophers eat?</code> 에 문의하면 원하는 결과를 얻지 못합니다:</p>[]
<p>간단한 키워드 검색을 통해 우리가 사용하는 애플리케이션에서 익숙한 방식으로 작동하는 성능 좋은 결과를 Go 애플리케이션에 반환할 수 있습니다. 또한 특정 회사나 용어를 찾는 것과 같은 시나리오와 관련된 정확한 용어 검색에도 유용합니다.</p><p>그러나 위에서 보았듯이 어휘 불일치 문제로 인해 문맥과 의미를 파악하는 데 어려움을 겪고 있습니다. 또한 이미지 및 오디오와 같은 텍스트가 아닌 파일 형식에 대한 지원도 어렵습니다.</p><h2>결론</h2><p>여기서는 Elasticsearch <a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Go 클라이언트를 사용하여 Elasticsearch에서 기존 텍스트 쿼리를 수행하는</a> 방법에 대해 설명했습니다. Go는 인프라 스크립팅과 웹 서버 구축에 널리 사용되므로 Go에서 검색하는 방법을 아는 것이 유용합니다.</p><p>이 시리즈의 모든 코드는 <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">GitHub 리포지토리에서</a> 확인하세요. <a href="https://www.elastic.co/search-labs/blog/perform-vector-search-with-the-elasticsearch-go-client">2부에서</a> 벡터 검색에 대한 개요와 Go에서 벡터 검색을 수행하는 방법을 알아보세요. 그때까지 고퍼 사냥을 즐기세요!</p><h2>리소스</h2><ol><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">Elasticsearch 가이드</a></p></li><li><p><a href="https://www.elastic.co/guide/en/elasticsearch/client/go-api/current/index.html">Elasticsearch Go 클라이언트</a></p></li><li><p><a href="https://codingexplained.com/coding/elasticsearch/understanding-analysis-in-elasticsearch-analyzers">보 앤더슨의 Elasticsearch(분석기)에서 분석 이해하기 | #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>