Retrieve specific fields
출처: 문서
본문
특정 필드 조회
OpenSearch에서 기본 검색을 실행하면 기본적으로 인덱싱할 때 사용된 원본 JSON 객체가 각 검색 결과의 _source 객체에 포함되어 응답으로 반환돼요. 이로 인해 네트워크를 통해 많은 양의 데이터가 전송되어 지연 시간과 비용이 증가할 수 있어요. 필요한 정보만 응답으로 받도록 제한하는 방법은 여러 가지가 있어요.
_source 비활성화
검색 요청에서 _source를 false로 설정하면 응답에서 _source 필드를 제외할 수 있어요:
GET /index1/_search
{
"_source": false,
"query": {
"match_all": {}
}
}
{% include copy-curl.html %}
앞선 검색에서 선택된 필드가 없었기 때문에 검색된 결과에는 _index, _id, _score만 포함돼요:
{
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "index1",
"_id" : "41",
"_score" : 1.0
},
{
"_index" : "index1",
"_id" : "51",
"_score" : 1.0
}
]
}
}
_source는 인덱스 매핑에서 다음 구성을 사용하여 비활성화할 수도 있어요:
"mappings": {
"_source": {
"enabled": false
}
}
인덱스 매핑에서 _source가 비활성화된 경우, docvalue 필드로 검색과 저장된 필드로 검색이 매우 유용해져요.
가져올 필드 지정
fields 매개변수에 가져오려는 필드를 나열할 수 있어요. 와일드카드 패턴도 허용돼요:
GET /index1/_search
{
"_source": false,
"fields": ["age", "nam*"],
"query": {
"match_all": {}
}
}
{% include copy-curl.html %}
응답에는 name과 age 필드가 포함돼요:
{
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "index1",
"_id" : "41",
"_score" : 1.0,
"fields" : {
"name" : [
"John Doe"
],
"age" : [
30
]
}
},
{
"_index" : "index1",
"_id" : "51",
"_score" : 1.0,
"fields" : {
"name" : [
"Jane Smith"
],
"age" : [
25
]
}
}
]
}
}
사용자 정의 형식으로 필드 추출
객체 표기법을 사용하여 선택한 필드에 사용자 정의 형식을 적용할 수도 있어요.
다음과 같은 문서가 있다면:
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_source": {
"title": "Document 1",
"date": "2023-07-04T12:34:56Z"
}
}
그런 다음 fields 매개변수와 사용자 정의 형식을 사용하여 쿼리할 수 있어요:
GET /my_index/_search
{
"query": {
"match_all": {}
},
"fields": [
{
"field": "date",
"format": "yyyy-MM-dd"
}
],
"_source": false
}
{% include copy-curl.html %}
또한 fields 매개변수는 문서의 _source와 인덱스의 _mappings를 모두 쿼리하기 때문에 대부분의 필드와 필드 별칭을 사용할 수 있어요.
doc value 필드로 검색
인덱스에서 특정 필드를 가져오려면 docvalue_fields 매개변수를 사용할 수도 있어요. 이 매개변수는 fields 매개변수와 약간 다르게 작동해요. _source 필드가 아닌 doc values에서 정보를 가져오는데, 이는 키워드, 날짜, 숫자 필드와 같이 분석되지 않은 필드에 더 효율적이에요. Doc values는 효율적인 정렬과 집계에 최적화된 컬럼형 저장 형식을 가지고 있어요. 디스크에 값을 읽기 쉬운 방식으로 저장해요. docvalue_fields를 사용하면 OpenSearch가 이 최적화된 저장 형식에서 직접 값을 읽어요. 주로 정렬, 집계 및 스크립트에서 사용되는 필드의 값을 가져올 때 유용해요.
다음 예제는 docvalue_fields 매개변수를 사용하는 방법을 보여줘요.
-
다음 매핑으로 인덱스를 생성하세요:
PUT /my_index { "mappings": { "properties": { "title": { "type": "text" }, "author": { "type": "keyword" }, "publication_date": { "type": "date" }, "price": { "type": "double" } } } }{% include copy-curl.html %}
-
새로 생성된 인덱스에 다음 문서를 인덱싱하세요:
POST /my_index/_doc/1 { "title": "OpenSearch Basics", "author": "John Doe", "publication_date": "2021-01-01", "price": 29.99 }{% include copy-curl.html %}
POST /my_index/_doc/2 { "title": "Advanced OpenSearch", "author": "Jane Smith", "publication_date": "2022-01-01", "price": 39.99 }{% include copy-curl.html %}
-
docvalue_fields를 사용하여author와publication_date필드만 가져오세요:POST /my_index/_search { "_source": false, "docvalue_fields": ["author", "publication_date"], "query": { "match_all": {} } }{% include copy-curl.html %}
응답에는 author와 publication_date 필드가 포함돼요:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"fields": {
"author": ["John Doe"],
"publication_date": ["2021-01-01T00:00:00.000Z"]
}
},
{
"_index": "my_index",
"_id": "2",
"_score": 1.0,
"fields": {
"author": ["Jane Smith"],
"publication_date": ["2022-01-01T00:00:00.000Z"]
}
}
]
}
}
docvalue_fields를 사용한 벡터 필드 검색
Introduced 3.7 {: .label .label-purple }
_source 대신 docvalue_fields를 사용하여 knn_vector 필드를 검색할 수 있어요. OpenSearch가 전체 _source 문서를 파싱하는 대신 doc_values에서 직접 벡터를 읽기 때문에 더 빨라요.
doc_values에서 knn_vector 필드를 검색하면 모든 벡터 데이터 타입(float, byte, binary), 모든 압축 수준, 모든 k-NN 엔진(Lucene, Faiss, NMSLIB)을 지원해요. 재인덱싱 없이 기존 인덱스에서 사용할 수 있어요.
성능 튜닝 지침은 doc values를 사용한 벡터 검색을 참조하세요.
다음 출력 형식이 지원돼요.
| 형식 | 설명 |
|---|---|
binary (기본값) |
벡터를 Base64로 인코딩된 리틀 엔디언 바이트 문자열로 반환해요. JSON 전송 시 array 형식보다 약 2배의 처리량 향상을 제공하고 응답 페이로드 크기를 30-40% 줄여요. |
array |
벡터를 JSON 숫자 배열로 반환해요. |
docvalue_fields를 사용하여 벡터 필드를 검색하려면 다음 단계를 따르세요:
-
knn_vector필드가 있는 인덱스를 생성하세요:PUT /my_vector_index { "settings": { "index.knn": true }, "mappings": { "properties": { "my_vector": { "type": "knn_vector", "dimension": 4 }, "title": { "type": "text" } } } }{% include copy-curl.html %}
-
문서를 인덱싱하세요:
POST /my_vector_index/_doc/1 { "my_vector": [1.0, 2.0, 3.0, 4.0], "title": "Sample document" }{% include copy-curl.html %}
-
기본
binary형식을 사용하여docvalue_fields로 벡터를 검색하세요:POST /my_vector_index/_search { "_source": false, "docvalue_fields": ["my_vector"], "query": { "knn": { "my_vector": { "vector": [1.0, 2.0, 3.0, 4.0], "k": 5 } } } }{% include copy-curl.html %}
응답은 벡터를 Base64로 인코딩된 문자열로 반환해요:
{ "hits": { "hits": [ { "_id": "1", "_score": 1.0, "fields": { "my_vector": ["AACAPwAAAEAAAEBAAACAQA=="] } } ] } } -
벡터를 JSON 숫자 배열로 검색하려면
array형식을 지정하세요:POST /my_vector_index/_search { "_source": false, "docvalue_fields": [{"field": "my_vector", "format": "array"}], "query": { "knn": { "my_vector": { "vector": [1.0, 2.0, 3.0, 4.0], "k": 5 } } } }{% include copy-curl.html %}
응답은 벡터를 숫자 배열로 반환해요:
{ "hits": { "hits": [ { "_id": "1", "_score": 1.0, "fields": { "my_vector": [[1.0, 2.0, 3.0, 4.0]] } } ] } }
doc_values를 사용하여 벡터를 검색하면서 _source에서 다른 문서 필드를 검색하려면 _source에서 벡터 필드를 제외하세요:
POST /my_vector_index/_search
{
"_source": {
"excludes": ["my_vector"]
},
"docvalue_fields": [{"field": "my_vector", "format": "array"}],
"query": {
"knn": {
"my_vector": {
"vector": [1.0, 2.0, 3.0, 4.0],
"k": 5
}
}
}
}
{% include copy-curl.html %}
중첩 객체와 docvalue_fields 사용
OpenSearch에서 중첩 객체의 doc values를 검색하려면 docvalue_fields 매개변수를 직접 사용할 수 없어요. 빈 배열을 반환하기 때문이에요. 대신 다음 예제와 같이 inner_hits 매개변수와 자체 docvalue_fields 속성을 사용해야 해요.
-
인덱스 매핑을 정의하세요:
PUT /my_index { "mappings": { "properties": { "title": { "type": "text" }, "author": { "type": "keyword" }, "comments": { "type": "nested", "properties": { "username": { "type": "keyword" }, "content": { "type": "text" }, "created_at": { "type": "date" } } } } } }{% include copy-curl.html %}
-
데이터를 인덱싱하세요:
POST /my_index/_doc/1 { "title": "OpenSearch Basics", "author": "John Doe", "comments": [ { "username": "alice", "content": "Great article!", "created_at": "2023-01-01T12:00:00Z" }, { "username": "bob", "content": "Very informative.", "created_at": "2023-01-02T12:00:00Z" } ] }{% include copy-curl.html %}
-
inner_hits와docvalue_fields로 검색을 수행하세요:POST /my_index/_search { "query": { "nested": { "path": "comments", "query": { "match_all": {} }, "inner_hits": { "docvalue_fields": ["username", "created_at"] } } } }{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"_source": {
"title": "OpenSearch Basics",
"author": "John Doe",
"comments": [
{
"username": "alice",
"content": "Great article!",
"created_at": "2023-01-01T12:00:00Z"
},
{
"username": "bob",
"content": "Very informative.",
"created_at": "2023-01-02T12:00:00Z"
}
]
},
"inner_hits": {
"comments": {
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 0
},
"docvalue_fields": {
"username": ["alice"],
"created_at": ["2023-01-01T12:00:00Z"]
}
},
{
"_index": "my_index",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 1
},
"docvalue_fields": {
"username": ["bob"],
"created_at": ["2023-01-02T12:00:00Z"]
}
}
]
}
}
}
}
]
}
}
저장된 필드로 검색
기본적으로 OpenSearch는 전체 문서를 _source 필드에 저장하고 이를 사용하여 검색 결과에 문서 내용을 반환해요. 하지만 특정 필드를 별도로 저장하여 더 효율적으로 검색하고 싶을 수도 있어요. stored_fields를 사용하여 특정 문서 필드를 _source 필드와 별도로 명시적으로 저장하고 검색할 수 있어요.
_source와 달리 stored_fields는 별도로 저장하려는 필드에 대해 매핑에서 명시적으로 정의해야 해요. 자주 소수의 필드만 검색해야 하고 전체 _source 필드를 검색하지 않으려는 경우 유용할 수 있어요. 다음 예제는 stored_fields 매개변수를 사용하는 방법을 보여줘요.
-
다음 매핑으로 인덱스를 생성하세요:
PUT /my_index { "mappings": { "properties": { "title": { "type": "text", "store": true // Store the title field separately }, "author": { "type": "keyword", "store": true // Store the author field separately }, "publication_date": { "type": "date" }, "price": { "type": "double" } } } }{% include copy-curl.html %}
-
데이터를 인덱싱하세요:
POST /my_index/_doc/1 { "title": "OpenSearch Basics", "author": "John Doe", "publication_date": "2022-01-01", "price": 29.99 }{% include copy-curl.html %}
POST my_index/_doc/2 { "title": "Advanced OpenSearch", "author": "Jane Smith", "publication_date": "2023-01-01", "price": 39.99 }{% include copy-curl.html %}
-
stored_fields로 검색을 수행하세요:POST /my_index/_search { "_source": false, "stored_fields": ["title", "author"], "query": { "match_all": {} } }{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"fields": {
"title": ["OpenSearch Basics"],
"author": ["John Doe"]
}
},
{
"_index": "my_index",
"_id": "2",
"_score": 1.0,
"fields": {
"title": ["Advanced OpenSearch"],
"author": ["Jane Smith"]
}
}
]
}
}
stored_fields 매개변수는 stored_fields를 _none_으로 설정하여 완전히 비활성화할 수 있어요.
{: .note}
중첩 객체로 저장된 필드 검색
OpenSearch에서 중첩 객체의 stored_fields를 검색하려면 stored_fields 매개변수를 직접 사용할 수 없어요. 데이터가 반환되지 않기 때문이에요. 대신 다음 예제와 같이 inner_hits 매개변수와 자체 stored_fields 속성을 사용해야 해요.
-
다음 매핑으로 인덱스를 생성하세요:
PUT /my_index { "mappings": { "properties": { "title": { "type": "text" }, "author": { "type": "keyword" }, "comments": { "type": "nested", "properties": { "username": { "type": "keyword", "store": true }, "content": { "type": "text", "store": true }, "created_at": { "type": "date", "store": true } } } } } }{% include copy-curl.html %}
-
데이터를 인덱싱하세요:
POST /my_index/_doc/1 { "title": "OpenSearch Basics", "author": "John Doe", "comments": [ { "username": "alice", "content": "Great article!", "created_at": "2023-01-01T12:00:00Z" }, { "username": "bob", "content": "Very informative.", "created_at": "2023-01-02T12:00:00Z" } ] }{% include copy-curl.html %}
-
inner_hits와stored_fields로 검색을 수행하세요:POST /my_index/_search { "_source": false, "query": { "nested": { "path": "comments", "query": { "match_all": {} }, "inner_hits": { "stored_fields": ["comments.username", "comments.content", "comments.created_at"] } } } }{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"inner_hits": {
"comments": {
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 0
},
"fields": {
"comments.username": ["alice"],
"comments.content": ["Great article!"],
"comments.created_at": ["2023-01-01T12:00:00.000Z"]
}
},
{
"_index": "my_index",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 1
},
"fields": {
"comments.username": ["bob"],
"comments.content": ["Very informative."],
"comments.created_at": ["2023-01-02T12:00:00.000Z"]
}
}
]
}
}
}
}
]
}
}
소스 필터링 사용
소스 필터링은 _source 필드의 어떤 부분을 검색 응답에 포함할지 제어하는 방법이에요. 응답에 필요한 필드만 포함하면 네트워크를 통해 전송되는 데이터 양을 줄이고 성능을 향상시킬 수 있어요.
전체 필드 이름이나 간단한 와일드카드 패턴을 사용하여 검색 응답의 _source 필드에서 특정 필드를 포함하거나 제외할 수 있어요. 다음 예제는 특정 필드를 포함하는 방법을 보여줘요.
-
데이터를 인덱싱하세요:
PUT /my_index/_doc/1 { "title": "OpenSearch Basics", "author": "John Doe", "publication_date": "2021-01-01", "price": 29.99 }{% include copy-curl.html %}
-
소스 필터링을 사용하여 검색을 수행하세요:
POST /my_index/_search { "_source": ["title", "author"], "query": { "match_all": {} } }{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"_source": {
"title": "OpenSearch Basics",
"author": "John Doe"
}
}
]
}
}
소스 필터링으로 필드 제외
검색 요청에서 "excludes" 매개변수를 사용하여 필드를 제외할 수 있어요. 다음 예제를 참조하세요:
POST /my_index/_search
{
"_source": {
"excludes": ["price"]
},
"query": {
"match_all": {}
}
}
{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 1.0,
"_source": {
"title": "OpenSearch Basics",
"author": "John Doe",
"publication_date": "2021-01-01"
}
}
]
}
}
동일한 검색에서 필드 포함 및 제외
경우에 따라 include와 exclude 매개변수가 모두 필요할 수 있어요. 필드가 두 목록의 패턴과 일치하면 OpenSearch는 해당 필드를 생략하는데, excludes가 includes보다 우선하기 때문이에요. 다음 예제는 동일한 검색에서 필드를 포함하고 제외하는 방법을 보여줘요.
다음 문서를 포함하는 products 인덱스를 생각해 보세요:
{
"product_id": "123",
"name": "Smartphone",
"category": "Electronics",
"price": 699.99,
"description": "A powerful smartphone with a sleek design.",
"reviews": [
{
"user": "john_doe",
"rating": 5,
"comment": "Great phone!",
"date": "2023-01-01"
},
{
"user": "jane_doe",
"rating": 4,
"comment": "Good value for money.",
"date": "2023-02-15"
}
],
"supplier": {
"name": "TechCorp",
"contact_email": "[email protected]",
"address": {
"street": "123 Tech St",
"city": "Techville",
"zipcode": "12345"
}
},
"inventory": {
"stock": 50,
"warehouse_location": "A1"
}
}
이 인덱스에서 검색을 수행할 때 응답에 name, price, reviews, supplier 필드만 포함하고 supplier 객체의 contact_email 필드와 reviews 객체의 comment 필드를 제외하려면 다음 검색을 실행하세요:
GET /products/_search
{
"_source": {
"includes": ["name", "price", "reviews.*", "supplier.*"],
"excludes": ["reviews.comment", "supplier.contact_email"]
},
"query": {
"match": {
"category": "Electronics"
}
}
}
{% include copy-curl.html %}
다음은 예상 응답이에요:
{
"hits": {
"hits": [
{
"_source": {
"name": "Smartphone",
"price": 699.99,
"reviews": [
{
"user": "john_doe",
"rating": 5,
"date": "2023-01-01"
},
{
"user": "jane_doe",
"rating": 4,
"date": "2023-02-15"
}
],
"supplier": {
"name": "TechCorp",
"address": {
"street": "123 Tech St",
"city": "Techville",
"zipcode": "12345"
}
}
}
}
]
}
}
소스 필터링 제한 사항
소스 필터링은 원본 JSON 문서의 필드 이름과 일치하므로 OpenSearch가 인덱싱 중에 파생하는 값은 반환할 수 없어요. 다중 필드, 필드 별칭, copy_to로 채워진 필드는 소스의 일부가 아니며, 해당 필드에 대한 요청은 빈 _source 객체를 반환해요.
OpenSearch는 요청이 몇 개의 필드만 요청하더라도 전체 소스 문서를 로드하고 파싱하므로 소스 필터링은 네트워크 전송을 줄이지만 디스크 읽기는 줄이지 않아요. 인덱스에서 개별 필드를 직접 읽으려면 docvalue_fields 또는 stored_fields를 사용하세요.
스크립트 필드 사용
script_fields 매개변수를 사용하면 스크립트로 계산된 사용자 정의 필드를 검색 결과에 포함할 수 있어요. 문서 데이터를 기반으로 값을 동적으로 계산할 때 유용해요. 비슷한 방법으로 derived fields를 검색할 수도 있어요. 자세한 내용은 필드 검색을 참조하세요.
각 제품 문서에 price와 discount_percentage 필드가 포함된 제품 인덱스가 있다고 가정해 보세요. script_fields 매개변수를 사용하여 각 제품의 할인된 가격을 표시하는 사용자 정의 필드를 검색 결과에 포함할 수 있어요. 다음 예제는 script_fields 매개변수를 사용하는 방법을 보여줘요.
-
데이터를 인덱싱하세요:
PUT /products/_doc/123 { "product_id": "123", "name": "Smartphone", "price": 699.99, "discount_percentage": 10, "category": "Electronics", "description": "A powerful smartphone with a sleek design." }{% include copy-curl.html %}
-
script_fields매개변수를 사용하여discounted_price라는 사용자 정의 필드를 검색 결과에 포함하세요. 이 필드는 스크립트를 사용하여price와discount_percentage필드를 기반으로 계산돼요:GET /products/_search { "_source": ["product_id", "name", "price", "discount_percentage"], "query": { "match": { "category": "Electronics" } }, "script_fields": { "discounted_price": { "script": { "lang": "painless", "source": "doc[\"price\"].value * (1 - doc[\"discount_percentage\"].value / 100)" } } } }{% include copy-curl.html %}
다음과 같은 응답을 받게 돼요:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "products",
"_id": "123",
"_score": 1.0,
"_source": {
"product_id": "123",
"name": "Smartphone",
"price": 699.99,
"discount_percentage": 10
},
"fields": {
"discounted_price": [629.991]
}
}
]
}
}