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 집계가 다시 결합한 부모 문서 수. 이 개수는 중첩 문서가 아닌 구별된 부모 문서를 반영해요.

더 알아보기 (Learn more)