Search your data

Cloud_ Ghost·2025년 9월 8일

opensearch

목록 보기
13/23

https://docs.opensearch.org/latest/getting-started/search-data/

데이터 검색하기

OpenSearch에서는 데이터를 검색하는 여러 가지 방법이 있습니다:

  • 쿼리 도메인 특화 언어(DSL): 복잡하고 완전히 사용자 정의 가능한 쿼리를 만들 수 있는 OpenSearch의 주요 쿼리 언어입니다.
  • 쿼리 문자열 쿼리 언어: 검색 요청의 쿼리 매개변수나 OpenSearch Dashboards에서 사용할 수 있는 축소된 쿼리 언어입니다.
  • SQL: 기존 관계형 데이터베이스 개념과 OpenSearch의 문서 지향 데이터 저장소의 유연성 사이의 격차를 메우는 전통적인 쿼리 언어입니다.
  • 파이프 처리 언어(PPL): OpenSearch에서 관찰성을 위해 사용되는 주요 언어입니다. PPL은 명령을 쿼리로 연결하는 파이프 구문을 사용합니다.
  • 대시보드 쿼리 언어(DQL): OpenSearch Dashboards에서 데이터를 필터링하기 위한 간단한 텍스트 기반 쿼리 언어입니다.

이 튜토리얼에는 쿼리 문자열 쿼리와 쿼리 DSL을 사용한 검색에 대한 간단한 소개가 포함되어 있습니다.

데이터 준비

이 튜토리얼을 위해 아직 학생 데이터를 인덱싱하지 않았다면 인덱싱해야 합니다. students 인덱스를 삭제(DELETE /students)한 다음 다음 일괄 요청을 보내는 것으로 시작할 수 있습니다:

POST _bulk
{ "create": { "_index": "students", "_id": "1" } }
{ "name": "John Doe", "gpa": 3.89, "grad_year": 2022}
{ "create": { "_index": "students", "_id": "2" } }
{ "name": "Jonathan Powers", "gpa": 3.85, "grad_year": 2025 }
{ "create": { "_index": "students", "_id": "3" } }
{ "name": "Jane Doe", "gpa": 3.52, "grad_year": 2024 }

인덱스의 모든 문서 검색

인덱스의 모든 문서를 검색하려면 다음 요청을 보내세요:

GET /students/_search

앞의 요청은 인덱스의 모든 문서와 일치하는 match_all 쿼리와 동일합니다:

GET /students/_search
{
  "query": {
    "match_all": {}
  }
}

OpenSearch는 일치하는 문서들을 반환합니다:

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "students",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "John Doe",
          "gpa": 3.89,
          "grad_year": 2022
        }
      },
      {
        "_index": "students",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "Jonathan Powers",
          "gpa": 3.85,
          "grad_year": 2025
        }
      },
      {
        "_index": "students",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "Jane Doe",
          "gpa": 3.52,
          "grad_year": 2024
        }
      }
    ]
  }
}

응답 본문 필드

앞의 응답에는 다음 필드들이 포함되어 있습니다.

took
took 필드는 쿼리가 실행되는 데 걸린 시간을 밀리초 단위로 포함합니다.

timed_out
이 필드는 요청이 시간 초과되었는지 여부를 나타냅니다. 요청이 시간 초과되면 OpenSearch는 시간 초과 전에 수집된 결과를 반환합니다. timeout 쿼리 매개변수를 제공하여 원하는 시간 초과 값을 설정할 수 있습니다:

GET /students/_search?timeout=20ms

_shards
_shards 객체는 쿼리가 실행된 총 샤드 수와 성공하거나 실패한 샤드 수를 지정합니다. 샤드 자체와 모든 레플리카를 사용할 수 없는 경우 샤드가 실패할 수 있습니다. 관련 샤드 중 하나라도 실패하면 OpenSearch는 나머지 샤드에서 쿼리를 계속 실행합니다.

hits
hits 객체는 일치하는 문서의 총 수와 문서 자체(hits 배열에 나열됨)를 포함합니다. 일치하는 각 문서는 _index 및 _id 필드와 완전히 원본 인덱싱된 문서를 포함하는 _source 필드를 포함합니다.

각 문서는 _score 필드에서 관련성 점수를 받습니다. match_all 검색을 실행했기 때문에 모든 문서 점수는 1로 설정됩니다(관련성에 차이가 없음). max_score 필드에는 일치하는 문서의 가장 높은 점수가 포함됩니다.

쿼리 문자열 쿼리

쿼리 문자열 쿼리는 가볍지만 강력합니다. 쿼리 문자열 쿼리를 q 쿼리 매개변수로 보낼 수 있습니다. 예를 들어, 다음 쿼리는 이름이 john인 학생을 검색합니다:

GET /students/_search?q=name:john

OpenSearch는 일치하는 문서를 반환합니다:

{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.9808291,
    "hits": [
      {
        "_index": "students",
        "_id": "1",
        "_score": 0.9808291,
        "_source": {
          "name": "John Doe",
          "gpa": 3.89,
          "grad_year": 2022
        }
      }
    ]
  }
}

쿼리 문자열 구문에 대한 자세한 정보는 "쿼리 문자열 쿼리 언어"를 참조하세요.

쿼리 DSL

쿼리 DSL을 사용하면 더 복잡하고 사용자 정의된 쿼리를 만들 수 있습니다.

전체 텍스트 검색

text로 매핑된 필드에서 전체 텍스트 검색을 실행할 수 있습니다. 기본적으로 텍스트 필드는 기본 분석기에 의해 분석됩니다. 분석기는 텍스트를 용어로 분할하고 소문자로 변경합니다. OpenSearch 분석기에 대한 자세한 정보는 "분석기"를 참조하세요.

예를 들어, 다음 쿼리는 이름이 john인 학생을 검색합니다:

GET /students/_search
{
  "query": {
    "match": {
      "name": "john"
    }
  }
}

응답에는 일치하는 문서가 포함됩니다:

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.9808291,
    "hits": [
      {
        "_index": "students",
        "_id": "1",
        "_score": 0.9808291,
        "_source": {
          "name": "John Doe",
          "gpa": 3.89,
          "grad_year": 2022
        }
      }
    ]
  }
}

쿼리 텍스트는 소문자이지만 필드의 텍스트는 그렇지 않지만, 쿼리는 여전히 일치하는 문서를 반환한다는 점에 주목하세요.

검색 문자열에서 용어를 재배열할 수 있습니다. 예를 들어, 다음 쿼리는 "doe john"을 검색합니다:

GET /students/_search
{
  "query": {
    "match": {
      "name": "doe john"
    }
  }
}

응답에는 두 개의 일치하는 문서가 포함됩니다:

{
  "took": 14,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.4508327,
    "hits": [
      {
        "_index": "students",
        "_id": "1",
        "_score": 1.4508327,
        "_source": {
          "name": "John Doe",
          "gpa": 3.89,
          "grad_year": 2022
        }
      },
      {
        "_index": "students",
        "_id": "3",
        "_score": 0.4700036,
        "_source": {
          "name": "Jane Doe",
          "gpa": 3.52,
          "grad_year": 2024
        }
      }
    ]
  }
}

match 쿼리 유형은 기본적으로 OR를 연산자로 사용하므로 쿼리는 기능적으로 "doe OR john"입니다. John Doe와 Jane Doe 모두 "doe"라는 단어와 일치했지만, John Doe는 "john"과도 일치했기 때문에 더 높은 점수를 받았습니다.

키워드 검색

name 필드에는 OpenSearch에서 자동으로 추가하는 name.keyword 하위 필드가 포함되어 있습니다. 이전 요청과 유사한 방식으로 name.keyword 필드를 검색하면:

GET /students/_search
{
  "query": {
    "match": {
      "name.keyword": "john"
    }
  }
}

키워드 필드는 정확히 일치해야 하므로 요청은 히트를 반환하지 않습니다.

그러나 정확한 텍스트 "John Doe"를 검색하면:

GET /students/_search
{
  "query": {
    "match": {
      "name.keyword": "John Doe"
    }
  }
}

OpenSearch는 일치하는 문서를 반환합니다:

{
  "took": 19,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.9808291,
    "hits": [
      {
        "_index": "students",
        "_id": "1",
        "_score": 0.9808291,
        "_source": {
          "name": "John Doe",
          "gpa": 3.89,
          "grad_year": 2022
        }
      }
    ]
  }
}

필터

Boolean 쿼리를 사용하여 정확한 값을 가진 필드에 대한 filter 절을 쿼리에 추가할 수 있습니다.

Term 필터는 특정 용어와 일치합니다. 예를 들어, 다음 Boolean 쿼리는 졸업년도가 2022인 학생을 검색합니다:

GET students/_search
{
  "query": { 
    "bool": { 
      "filter": [ 
        { "term":  { "grad_year": 2022 }}
      ]
    }
  }
}

Range 필터를 사용하면 값의 범위를 지정할 수 있습니다. 예를 들어, 다음 Boolean 쿼리는 GPA가 3.6보다 큰 학생을 검색합니다:

GET students/_search
{
  "query": { 
    "bool": { 
      "filter": [ 
        { "range": { "gpa": { "gt": 3.6 }}}
      ]
    }
  }
}

필터에 대한 자세한 정보는 "쿼리 및 필터 컨텍스트"를 참조하세요.

복합 쿼리

복합 쿼리를 사용하면 여러 쿼리나 필터 절을 결합할 수 있습니다. Boolean 쿼리는 복합 쿼리의 예입니다.

예를 들어, 이름이 "doe"와 일치하는 학생을 검색하고 졸업년도와 GPA로 필터링하려면 다음 요청을 사용하세요:

GET students/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "doe"
          }
        },
        { "range": { "gpa": { "gte": 3.6, "lte": 3.9 } } },
        { "term":  { "grad_year": 2022 }}
      ]
    }
  }
}

Boolean 및 기타 복합 쿼리에 대한 자세한 정보는 "복합 쿼리"를 참조하세요.

검색 방법

이 튜토리얼에서 설명한 기존 전체 텍스트 검색과 함께 OpenSearch는 k-NN, 의미론적, 다중모달, 희소, 하이브리드, 대화형 검색을 포함한 다양한 기계 학습(ML) 기반 검색 방법을 지원합니다. OpenSearch에서 지원하는 모든 검색 방법에 대한 정보는 "검색"을 참조하세요.

다음 단계

  • 사용 가능한 쿼리 유형에 대한 정보는 "쿼리 DSL"을 참조하세요.
  • 사용 가능한 검색 방법에 대한 정보는 "검색"을 참조하세요.

OpenSearch 데이터 검색에 대한 문서를 한국어로 번역해드리겠습니다.검색 가이드 번역이 완료되었습니다! 이제 이 문서도 쿡북 형태로 활용할 수 있도록 몇 가지 제안드리겠습니다:

쿡북 스타일 개선 방안

1. 검색 유형별 선택 가이드:

## 언제 어떤 검색을 사용할까?

### 간단한 키워드 검색
→ 쿼리 문자열: `?q=name:john`

### 유연한 텍스트 검색  
→ match 쿼리: 오타 허용, 순서 무관

### 정확한 일치 검색
→ keyword 필드: 대소문자, 띄어쓰기 정확히 일치

### 숫자/날짜 범위 검색
→ range 필터: `"gte": 3.6, "lte": 3.9`

### 복합 조건 검색
→ bool 쿼리: must/should/filter 조합

2. 자주 사용하는 쿼리 패턴:

## 실무에서 자주 쓰는 패턴

### 기본 검색
- 전체 조회: `GET /인덱스/_search`
- 특정 필드: `GET /인덱스/_search?q=필드:값`

### 필터링 조합
- AND 조건: bool.must 사용
- OR 조건: bool.should 사용  
- 제외 조건: bool.must_not 사용

### 성능 최적화
- 필터 우선: filter는 캐시됨
- 정확한 매칭: keyword 필드 활용
- 시간 초과: ?timeout=30s 설정

3. 점수 이해하기:

## 검색 점수(_score) 해석

### 점수가 높을수록 관련성 높음
- match_all: 모든 문서 1.0
- 키워드 일치: 빈도에 따라 변동
- 여러 조건: 조건별 점수 합산

### 점수에 영향을 주는 요소
1. 단어 빈도 (TF)
2. 역문서 빈도 (IDF)  
3. 문서 길이 정규화
profile
행복합시다~

0개의 댓글