Collapsing hybrid query results
출처: 문서
본문
하이브리드 쿼리 결과 접기
3.1에 도입됨 {: .label .label-purple }
collapse 매개변수를 사용하면 필드별로 결과를 그룹화하여 각 고유 필드 값에 대해 가장 높은 점수를 받은 문서만 반환할 수 있어요. 검색 결과에서 중복을 피하고 싶을 때 유용해요. 접는 필드는 keyword 또는 숫자 유형이어야 해요. 반환되는 결과 수는 여전히 쿼리의 size 매개변수에 의해 제한돼요.
collapse 매개변수는 정렬, 설명, 페이지 매김과 같은 다른 하이브리드 쿼리 검색 옵션과 호환되며, 표준 구문을 사용해요.
하이브리드 쿼리에서 collapse를 사용할 때는 다음 사항에 유의하세요:
index.neural_search.hybrid_collapse_docs_per_group_per_subquery설정은 더 이상 사용되지 않으며 효과가 없어요. 이 설정이 인덱스 구성에 존재한다면 안전하게 제거할 수 있어요. 검색 결과는 전적으로 검색 요청의size매개변수에 의해 제어돼요.- 기본적으로 하이브리드 쿼리에
collapse매개변수가 포함되면 OpenSearch는 상위size문서를 중복 제거해요. 결과적으로 여러 상위 점수 문서가 동일한 그룹에 속하는 경우 응답에size보다 적은 그룹이 포함될 수 있어요. 최대size개의 고유 그룹을 반환하려면index.neural_search.hybrid_collapse_distinct_groups_enabled설정을 활성화하세요. 자세한 내용은 고유 그룹 반환을 참조하세요. - 집계는 접기 전 결과에 대해 실행되며 최종 출력에 대해 실행되지 않아요.
- 페이지 매김 동작이 변경돼요:
collapse가 전체 결과 수를 줄이기 때문에 페이지 전체에 결과가 분산되는 방식에 영향을 줄 수 있어요. 더 많은 결과를 검색하려면 페이지 매김 깊이를 늘리는 것을 고려하세요. - 결과는 쿼리 실행 후 접기 논리를 적용하는
collapse응답 프로세서가 반환하는 결과와 다를 수 있어요.
예제
다음 예제는 하이브리드 쿼리 결과를 접는 방법을 보여줘요.
인덱스를 생성하세요:
PUT /bakery-items
{
"mappings": {
"properties": {
"item": {
"type": "keyword"
},
"category": {
"type": "keyword"
},
"price": {
"type": "float"
},
"baked_date": {
"type": "date"
}
}
}
}
{% include copy-curl.html %}
인덱스에 문서를 수집하세요:
POST /bakery-items/_bulk
{ "index": {} }
{ "item": "Chocolate Cake", "category": "cakes", "price": 15, "baked_date": "2023-07-01T00:00:00Z" }
{ "index": {} }
{ "item": "Chocolate Cake", "category": "cakes", "price": 18, "baked_date": "2023-07-04T00:00:00Z" }
{ "index": {} }
{ "item": "Vanilla Cake", "category": "cakes", "price": 12, "baked_date": "2023-07-02T00:00:00Z" }
{ "index": {} }
{ "item": "Vanilla Cake", "category": "cakes", "price": 16, "baked_date": "2023-07-03T00:00:00Z" }
{ "index": {} }
{ "item": "Vanilla Cake", "category": "cakes", "price": 17, "baked_date": "2023-07-09T00:00:00Z" }
{% include copy-curl.html %}
검색 파이프라인을 생성하세요. 이 예제는 min_max 정규화 기법을 사용해요:
PUT /_search/pipeline/norm-pipeline
{
"description": "Normalization processor for hybrid search",
"phase_results_processors": [
{
"normalization-processor": {
"normalization": {
"technique": "min_max"
},
"combination": {
"technique": "arithmetic_mean"
}
}
}
]
}
{% include copy-curl.html %}
인덱스를 검색하고 item 필드별로 검색 결과를 그룹화하세요:
GET /bakery-items/_search?search_pipeline=norm-pipeline
{
"query": {
"hybrid": {
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"collapse": {
"field": "item"
}
}
{% include copy-curl.html %}
응답은 접힌 검색 결과를 반환해요:
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "bakery-items",
"_id": "wBRPZZcB49c_2-1rYmO7",
"_score": 1.0,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
}
},
{
"_index": "bakery-items",
"_id": "whRPZZcB49c_2-1rYmO7",
"_score": 0.5005,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
}
}
]
}
고유 그룹 반환
3.10에 도입됨 {: .label .label-purple }
기본적으로 하이브리드 쿼리에 collapse 매개변수가 포함되면 OpenSearch는 상위 size 문서를 유지한 다음 collapse 매개변수에 지정된 필드별로 중복을 제거해요. 점수는 collapse 매개변수가 제공되지 않은 동일한 하이브리드 쿼리가 반환하는 점수와 일치해요. 그러나 여러 상위 점수 문서가 동일한 그룹에 속하는 경우 응답에 size보다 적은 그룹이 포함될 수 있어요.
예를 들어, 이전 예제의 bakery-items 인덱스를 검색하여 두 개의 결과를 요청하세요:
GET /bakery-items/_search?search_pipeline=norm-pipeline
{
"size": 2,
"query": {
"hybrid": {
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"collapse": {
"field": "item"
}
}
{% include copy-curl.html %}
응답에는 요청이 "size": 2를 지정하고 두 그룹이 존재함에도 불구하고 하나의 결과만 포함돼요. 상위 두 문서 모두 Chocolate Cake 그룹에 속하므로 중복 제거 후 단일 그룹만 남아요:
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "bakery-items",
"_id": "_w1VyqAB-8qXmeJq0uk4",
"_score": 1.0,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
}
}
]
}
대신 상위 size개의 고유 그룹을 반환하려면 인덱스에서 index.neural_search.hybrid_collapse_distinct_groups_enabled 설정을 활성화하세요:
PUT /bakery-items/_settings
{
"index.neural_search.hybrid_collapse_distinct_groups_enabled": true
}
{% include copy-curl.html %}
동일한 검색을 실행하면 이제 상위 두 개의 고유 그룹 각각에 대해 하나의 결과를 반환해요:
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "bakery-items",
"_id": "_w1VyqAB-8qXmeJq0uk4",
"_score": 1.0,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
}
},
{
"_index": "bakery-items",
"_id": "AQ1VyqAB-8qXmeJq0uo4",
"_score": 0.5,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
}
}
]
}
index.neural_search.hybrid_collapse_distinct_groups_enabled 설정이 활성화되면 반환된 각 문서는 해당 그룹을 대표해요. 각 하위 쿼리에 대해 OpenSearch는 반환된 문서에 해당 그룹의 모든 문서 중 최고 점수를 할당해요. 서로 다른 하위 쿼리의 최고 점수는 동일한 그룹의 다른 문서에 속할 수 있어요. 최고 점수는 결과가 점수 내림차순(기본값)으로 정렬될 때 가장 높은 점수이고, 점수 오름차순으로 정렬될 때 가장 낮은 점수예요.
정규화는 대표 문서에 대해 실행돼요. 결과적으로 점수는 collapse 매개변수가 제공되지 않은 동일한 하이브리드 쿼리가 반환하는 점수와 다를 수 있어요.
index.neural_search.hybrid_collapse_distinct_groups_enabled 설정은 동적이며 모든 요청에서 읽히므로 페이지가 매겨진 검색의 페이지 사이에서 이 설정을 변경하면 일관되지 않은 페이지가 생성돼요. 동일한 요청에서 이 설정에 대해 다른 값을 가진 인덱스를 검색하지 마세요.
{: .note}
접기 및 결과 정렬
하이브리드 쿼리 결과를 접고 정렬하려면 쿼리에 collapse 및 sort 매개변수를 제공하세요:
GET /bakery-items/_search?search_pipeline=norm-pipeline
{
"query": {
"hybrid": {
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"collapse": {
"field": "item"
},
"sort": "price"
}
{% include copy-curl.html %}
하이브리드 쿼리 정렬에 대한 자세한 내용은 하이브리드 쿼리와 함께 정렬 사용을 참조하세요.
응답에서 문서는 가장 낮은 가격순으로 정렬돼요:
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "bakery-items",
"_id": "whRPZZcB49c_2-1rYmO7",
"_score": null,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
},
"sort": [
12.0
]
},
{
"_index": "bakery-items",
"_id": "wBRPZZcB49c_2-1rYmO7",
"_score": null,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
},
"sort": [
15.0
]
}
]
}
접기 및 설명
검색 결과를 접을 때 explain 쿼리 매개변수를 제공할 수 있어요:
GET /bakery-items/_search?search_pipeline=norm-pipeline&explain=true
{
"query": {
"hybrid": {
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"collapse": {
"field": "item"
}
}
{% include copy-curl.html %}
응답에는 각 검색 결과에 대한 점수 계산 과정에 대한 자세한 정보가 포함돼요:
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_shard": "[bakery-items][0]",
"_node": "Jlu8P9EaQCy3C1BxaFMa_g",
"_index": "bakery-items",
"_id": "3ZILepcBheX09_dPt8TD",
"_score": 1.0,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
},
"_explanation": {
"value": 1.0,
"description": "combined score of:",
"details": [
{
"value": 1.0,
"description": "ConstantScore(item:Chocolate Cake)",
"details": []
},
{
"value": 1.0,
"description": "ConstantScore(category:cakes)",
"details": []
}
]
}
},
{
"_shard": "[bakery-items][0]",
"_node": "Jlu8P9EaQCy3C1BxaFMa_g",
"_index": "bakery-items",
"_id": "35ILepcBheX09_dPt8TD",
"_score": 0.5005,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
},
"_explanation": {
"value": 1.0,
"description": "combined score of:",
"details": [
{
"value": 0.0,
"description": "ConstantScore(item:Chocolate Cake) doesn't match id 2",
"details": []
},
{
"value": 1.0,
"description": "ConstantScore(category:cakes)",
"details": []
}
]
}
}
]
}
하이브리드 쿼리에서 explain 사용에 대한 자세한 내용은 하이브리드 검색 설명을 참조하세요.
접기 및 페이지 매김
from 및 size 매개변수를 제공하여 접힌 결과를 페이지 매김할 수 있어요. 하이브리드 쿼리의 페이지 매김에 대한 자세한 내용은 하이브리드 쿼리 결과 페이지 매김을 참조하세요. from 및 size에 대한 자세한 내용은 from 및 size 매개변수를 참조하세요.
이 예제를 위해 다음 인덱스를 생성하세요:
PUT /bakery-items-pagination
{
"settings": {
"index.number_of_shards": 3
},
"mappings": {
"properties": {
"item": {
"type": "keyword"
},
"category": {
"type": "keyword"
},
"price": {
"type": "float"
},
"baked_date": {
"type": "date"
}
}
}
}
{% include copy-curl.html %}
인덱스에 다음 문서를 수집하세요:
POST /bakery-items-pagination/_bulk
{ "index": {} }
{ "item": "Chocolate Cake", "category": "cakes", "price": 15, "baked_date": "2023-07-01T00:00:00Z" }
{ "index": {} }
{ "item": "Chocolate Cake", "category": "cakes", "price": 18, "baked_date": "2023-07-02T00:00:00Z" }
{ "index": {} }
{ "item": "Vanilla Cake", "category": "cakes", "price": 12, "baked_date": "2023-07-02T00:00:00Z" }
{ "index": {} }
{ "item": "Vanilla Cake", "category": "cakes", "price": 11, "baked_date": "2023-07-04T00:00:00Z" }
{ "index": {} }
{ "item": "Ice Cream Cake", "category": "cakes", "price": 23, "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Ice Cream Cake", "category": "cakes", "price": 22, "baked_date": "2023-07-10T00:00:00Z" }
{ "index": {} }
{ "item": "Carrot Cake", "category": "cakes", "price": 24, "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Carrot Cake", "category": "cakes", "price": 26, "baked_date": "2023-07-21T00:00:00Z" }
{ "index": {} }
{ "item": "Red Velvet Cake", "category": "cakes", "price": 25, "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Red Velvet Cake", "category": "cakes", "price": 29, "baked_date": "2023-07-30T00:00:00Z" }
{ "index": {} }
{ "item": "Cheesecake", "category": "cakes", "price": 27. "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Cheesecake", "category": "cakes", "price": 34. "baked_date": "2023-07-21T00:00:00Z" }
{ "index": {} }
{ "item": "Coffee Cake", "category": "cakes", "price": 42, "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Coffee Cake", "category": "cakes", "price": 41, "baked_date": "2023-07-05T00:00:00Z" }
{ "index": {} }
{ "item": "Cocunut Cake", "category": "cakes", "price": 23, "baked_date": "2023-07-09T00:00:00Z" }
{ "index": {} }
{ "item": "Cocunut Cake", "category": "cakes", "price": 32, "baked_date": "2023-07-12T00:00:00Z" }
// Additional documents omitted for brevity
{% include copy-curl.html %}
hybrid 쿼리를 실행하고 from 및 size 매개변수를 지정하여 결과를 페이지 매김하세요. 다음 예제에서 쿼리는 여섯 번째 위치부터 두 개의 결과를 요청해요(from: 5, size: 2). 페이지 매김 깊이는 각 샤드가 최대 10개의 문서를 반환하도록 제한하도록 설정돼요. 결과가 검색된 후 collapse 매개변수가 적용되어 item 필드별로 그룹화해요:
GET /bakery-items-pagination/_search?search_pipeline=norm-pipeline
{
"query": {
"hybrid": {
"pagination_depth": 10,
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"from": 5,
"size": 2,
"collapse": {
"field": "item"
}
}
{% include copy-curl.html %}
"hits": {
"total": {
"value": 70,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "bakery-items-pagination",
"_id": "gDayepcBIkxlgFKYda0p",
"_score": 0.5005,
"_source": {
"item": "Red Velvet Cake",
"category": "cakes",
"price": 29,
"baked_date": "2023-07-30T00:00:00Z"
},
"fields": {
"item": [
"Red Velvet Cake"
]
}
},
{
"_index": "bakery-items-pagination",
"_id": "aTayepcBIkxlgFKYca15",
"_score": 0.5005,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
}
}
]
}
접힌 하이브리드 쿼리 결과에 대한 내부 적중 검색
3.2에 도입됨 {: .label .label-purple }
collapse 매개변수 내에서 inner_hits 매개변수를 사용하여 각 접힌 그룹에서 추가 문서를 검색할 수 있어요.
다음 예제는 이전에 생성된 bakery-items 인덱스를 사용해요. 케이크 항목을 검색하고 item 필드별로 결과를 접고(그룹화) 각 접힌 값에 대해 가장 저렴한 두 항목을 반환해요:
GET /bakery-items/_search?search_pipeline=norm-pipeline
{
"query": {
"hybrid": {
"queries": [
{
"match": {
"item": "Chocolate Cake"
}
},
{
"bool": {
"must": {
"match": {
"category": "cakes"
}
}
}
}
]
}
},
"collapse": {
"field": "item",
"inner_hits": [
{
"name": "cheapest_items",
"size": 2,
"sort": ["price"]
}
]
}
}
{% include copy-curl.html %}
응답에서 기본 hits는 각 접힌 그룹의 최고 점수 문서를 포함해요. inner_hits는 각 그룹에서 가장 저렴한 두 항목을 포함해요:
응답
{: .text-delta}{
...
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "bakery-items",
"_id": "bIe6e5gBAB5HT6ixTd4F",
"_score": 1,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"fields": {
"item": [
"Chocolate Cake"
]
},
"inner_hits": {
"cheapest_items": {
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "bakery-items",
"_id": "bIe6e5gBAB5HT6ixTd4F",
"_score": null,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 15,
"baked_date": "2023-07-01T00:00:00Z"
},
"sort": [
15
]
},
{
"_index": "bakery-items",
"_id": "bYe6e5gBAB5HT6ixTd4F",
"_score": null,
"_source": {
"item": "Chocolate Cake",
"category": "cakes",
"price": 18,
"baked_date": "2023-07-04T00:00:00Z"
},
"sort": [
18
]
}
]
}
}
}
},
{
"_index": "bakery-items",
"_id": "boe6e5gBAB5HT6ixTd4F",
"_score": 0.5005,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"fields": {
"item": [
"Vanilla Cake"
]
},
"inner_hits": {
"cheapest_items": {
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "bakery-items",
"_id": "boe6e5gBAB5HT6ixTd4F",
"_score": null,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 12,
"baked_date": "2023-07-02T00:00:00Z"
},
"sort": [
12
]
},
{
"_index": "bakery-items",
"_id": "b4e6e5gBAB5HT6ixTd4F",
"_score": null,
"_source": {
"item": "Vanilla Cake",
"category": "cakes",
"price": 16,
"baked_date": "2023-07-03T00:00:00Z"
},
"sort": [
16
]
}
]
}
}
}
}
]
}
}