Reverse nested 집계
Reverse nested 집계
reverse_nested 집계를 사용하면 중첩(nested) 집계 컨텍스트 안에서 부모 문서 필드에 대해 집계할 수 있어요. 중첩 필드로 그룹화하면 집계 컨텍스트가 중첩 문서로 이동해요. reverse_nested 집계는 이 중첩 컨텍스트에서 벗어나 부모(또는 루트) 문서로 다시 결합하여, 부모 필드를 추가 하위 집계에서 접근할 수 있게 해요.
reverse_nested 집계는 반드시 nested 집계 안에 정의되어야 해요.
출처: 문서
본문
파라미터 (Parameters)
reverse_nested 집계는 다음 파라미터를 받아요.
| 파라미터 | 필수/선택 | 데이터 타입 | 설명 |
|---|---|---|---|
| path | 선택 | String | 다시 결합할 중첩 객체 경로. 기본값은 비어 있음(루트 문서로 다시 결합). 다중 레벨 중첩의 경우 루트 대신 해당 레벨로 결합할 중간 중첩 경로를 지정해요. |
예제 설정 (Example setup)
중첩된 comments가 있는 issues를 포함하는 인덱스를 만들어요:
PUT /issues
{
"mappings": {
"properties": {
"title": { "type": "text" },
"tags": { "type": "keyword" },
"comments": {
"type": "nested",
"properties": {
"username": { "type": "keyword" },
"comment": { "type": "text" }
}
}
}
}
}
몇몇 문서를 색인해요:
POST /issues/_bulk?refresh=true
{"index":{"_id":"1"}}
{"title":"Add dark mode to settings page","tags":["ui","enhancement"],"comments":[{"username":"alice","comment":"Would love this feature"},{"username":"bob","comment":"Should support system preference detection"}]}
{"index":{"_id":"2"}}
{"title":"Export report as PDF","tags":["export","enhancement"],"comments":[{"username":"alice","comment":"CSV export would also be useful"},{"username":"carol","comment":"Added to the roadmap"}]}
{"index":{"_id":"3"}}
{"title":"Improve mobile navigation","tags":["ui","mobile"],"comments":[{"username":"bob","comment":"Hamburger menu would work well"},{"username":"carol","comment":"Agree, especially for tablets"}]}
예제 (Example)
다음 예제는 가장 활동적인 댓글 작성자를 찾은 다음 reverse_nested를 사용해 각 작성자가 가장 많이 관여한 이슈 태그를 확인해요. reverse_nested가 없으면 집계 컨텍스트가 중첩된 comments 객체 안에 있기 때문에 tags 필드에 접근할 수 없어요:
GET /issues/_search
{
"size": 0,
"aggs": {
"comments": {
"nested": {
"path": "comments"
},
"aggs": {
"top_commenters": {
"terms": {
"field": "comments.username"
},
"aggs": {
"back_to_issue": {
"reverse_nested": {},
"aggs": {
"top_tags": {
"terms": {
"field": "tags"
}
}
}
}
}
}
}
}
}
}
응답은 Bob의 댓글이 "ui"(2개 이슈), "enhancement"(1개), "mobile"(1개)로 태그된 이슈에 나타남을 보여줘요:
{
...
"aggregations": {
"comments": {
"doc_count": 6,
"top_commenters": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "alice",
"doc_count": 2,
"back_to_issue": {
"doc_count": 2,
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "enhancement",
"doc_count": 2
},
{
"key": "export",
"doc_count": 1
},
{
"key": "ui",
"doc_count": 1
}
]
}
}
},
{
"key": "bob",
"doc_count": 2,
"back_to_issue": {
"doc_count": 2,
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "ui",
"doc_count": 2
},
{
"key": "enhancement",
"doc_count": 1
},
{
"key": "mobile",
"doc_count": 1
}
]
}
}
},
{
"key": "carol",
"doc_count": 2,
"back_to_issue": {
"doc_count": 2,
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "enhancement",
"doc_count": 1
},
{
"key": "export",
"doc_count": 1
},
{
"key": "mobile",
"doc_count": 1
},
{
"key": "ui",
"doc_count": 1
}
]
}
}
}
]
}
}
}
}
예제: 다중 레벨 중첩에서 path 파라미터 사용 (Example: Using the path parameter with multi-level nesting)
문서가 중첩 객체 안에 중첩 객체를 포함할 때 path 파라미터를 사용해 루트 대신 중간 레벨로 결합할 수 있어요. 다음 예제는 게시물이 중첩된 comments를 포함하고 각 comment가 중첩된 replies를 포함하는 포럼 스타일 구조를 사용해요:
PUT /forum_posts
{
"mappings": {
"properties": {
"title": { "type": "keyword" },
"comments": {
"type": "nested",
"properties": {
"author": { "type": "keyword" },
"replies": {
"type": "nested",
"properties": {
"author": { "type": "keyword" }
}
}
}
}
}
}
}
comments와 replies가 있는 게시물을 색인해요:
POST /forum_posts/_doc/1?refresh=true
{
"title": "Post A",
"comments": [
{ "author": "alice", "replies": [{"author": "bob"}, {"author": "carol"}] },
{ "author": "bob", "replies": [{"author": "alice"}] }
]
}
다음 집계는 reply 작성자로 그룹화한 다음 "path": "comments"로 reverse_nested를 사용해 comment 레벨(루트가 아닌)로 결합하고 각 사람이 어떤 comment 작성자에게 답글을 달았는지 찾아요:
GET /forum_posts/_search
{
"size": 0,
"aggs": {
"comments": {
"nested": { "path": "comments" },
"aggs": {
"replies": {
"nested": { "path": "comments.replies" },
"aggs": {
"reply_authors": {
"terms": { "field": "comments.replies.author" },
"aggs": {
"back_to_comment": {
"reverse_nested": { "path": "comments" },
"aggs": {
"comment_authors": {
"terms": { "field": "comments.author" }
}
}
}
}
}
}
}
}
}
}
}
응답은 Bob가 Alice의 댓글에 답글을 달았고 Carol도 Alice의 댓글에 답글을 달았음을 보여줘요:
{
...
"aggregations": {
"comments": {
"doc_count": 2,
"replies": {
"doc_count": 3,
"reply_authors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "alice",
"doc_count": 1,
"back_to_comment": {
"doc_count": 1,
"comment_authors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "bob",
"doc_count": 1
}
]
}
}
},
{
"key": "bob",
"doc_count": 1,
"back_to_comment": {
"doc_count": 1,
"comment_authors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "alice",
"doc_count": 1
}
]
}
}
},
{
"key": "carol",
"doc_count": 1,
"back_to_comment": {
"doc_count": 1,
"comment_authors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "alice",
"doc_count": 1
}
]
}
}
}
]
}
}
}
}
}
응답 본문 필드 (Response body fields)
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
| doc_count | Integer | 집계가 다시 결합한 부모 문서 수. 이 개수는 중첩 문서가 아닌 구별된 부모 문서를 반영해요. |