elasticsearch 기초 - Parent-Child 부자 관계(5.X 이전 버전)

8640 단어 ELKelasticsearch
ElasticSearch의 Parent-Child 관계와 nested 모델은 비슷하다. 두 가지 모두 복잡한 데이터 구조에 사용할 수 있다. 차이점은 nested 유형의 문서는 모든 실체를 하나의 문서에 집합하는 것이다. Parent-Child는 현재 비교적 독립적이다. 각 실체는 하나의 문서인 Parent-Child의 장점 1. 부모 문서를 업데이트할 때 하위 문서를 다시 인덱스하지 않아도 된다. 2, 하위 문서의 증가, 수정,삭제는 부모 문서와 다른 하위 문서에 아무런 영향을 미치지 않습니다. 이것은 하위 문서가 매우 크고 새로운 빈번한 장면에 적용됩니다. 3. 하위 문서와 검색 결과는 ElasticSearch 내부에서 맵을 유지하여 Parent-child 간의 관계를 저장할 수 있습니다. 바로 이 맵 때문에 관련 검색은 응답 속도가 매우 빠릅니다.하지만 Parent 문서와 모든 Child 문서는 같은 shard에 저장해야 한다는 제한이 있습니다. ElasticSearch parent-child ID의 맵은 Doc value에 저장되고 충분한 메모리가 있을 때 응답이 빠릅니다.이 맵이 매우 크면 일부분은 하드디스크에 저장해야 한다.

Parent-Child Mapping


Parent-Child 모델을 구축하기 위해서는 맵핑을 만들 때 부모 문서와 하위 문서를 지정하거나 하위 문서를 만들기 전에 update-index API를 이용하여 지정해야 합니다. 예를 들어 우리는 회사가 하나 있는데 그 자회사는 전국 각지에 분포되어 있습니다. 저는 직원과 자회사의 관계를 분석해야 합니다. 우리는 Parent-Child 기구를 사용하고employee type과 branch type을 구축하고 branch를_로 지정해야 합니다.parent
PUT /company
{
   "mappings": {
        "branch": {},
         "employee": {
             "_parent": {
                      "type": "branch"
              }
         }
     }
}

Indexing Parents and Children


부모 색인을 만드는 것과 다른 색인을 만드는 것은 다르지 않습니다. 부모 문서는 그들의 하위 문서를 알 필요가 없습니다.
POST /company/branch/_bulk
{ "index": { "_id": "london" }}
{ "name": "London Westminster", "city": "London", "country": "UK" }
{ "index": { "_id": "liverpool" }}
{ "name": "Liverpool Central", "city": "Liverpool", "country": "UK" }
{ "index": { "_id": "paris" }}
{ "name": "Champs Élysées", "city": "Paris", "country": "France" }

하위 문서를 만들 때 부모 문서의 id를 지적해야 합니다
PUT /company/employee/1?parent=london 
{
  "name":  "Alice Smith",
  "dob":   "1970-10-24",
  "hobby": "hiking"
}

parent id를 지정하는 데는 두 가지 목적이 있습니다. 그는 아버지 문서와 하위 문서의 관련입니다. 그리고 아버지 문서와 하위 문서가 같은shard에 저장될 것을 보장합니다. 루팅 부분에서 우리는 ElasticSearch가 루팅 값을 어떻게 이용하여shard에 분배를 결정하는지 설명했습니다. 만약에 문서가routing의 값을 지정하지 않았다면 기본값은_id, 공식은
shard = hash(routing) % number_of_primary_shards

하지만,parent id를 지정하면routing의 값은_id는 parent id입니다. 다시 말하면 부모 문서와 하위 문서는 같은routing의 값을 가지고 있기 때문에 그들이 같은shard에 분배될 수 있도록 합니다. 우리가 GET 요청으로 하위 문서를 검사할 때 parent id를 지정해야 합니다. 그리고 색인을 만들고 업데이트해야 합니다. 색인을 삭제하려면 모두parent id를 지정해야 합니다. 검색된 요청과 달리 모든shard에 나누어 줍니다.이single-document 요청은 저장된shard에만 전송됩니다.parent id를 지정하지 않으면 잘못된 shard로 요청할 수 있습니다. buk API를 사용할 때parent id를 지정해야 합니다.
POST /company/employee/_bulk
{ "index": { "_id": 2, "parent": "london" }}
{ "name": "Mark Thomas", "dob": "1982-05-16", "hobby": "diving" }
{ "index": { "_id": 3, "parent": "liverpool" }}
{ "name": "Barry Smith", "dob": "1979-04-01", "hobby": "hiking" }
{ "index": { "_id": 4, "parent": "paris" }}
{ "name": "Adrien Grand", "dob": "1987-05-11", "hobby": "horses" }

Finding Parents by Their Children


has_child와 filter는 하위 문서의 내용에 따라 상위 문서를 조회할 수 있습니다. 예를 들어 우리는 1980년 이후 태어난 모든 지사를 검색할 수 있습니다.
GET /company/branch/_search
{
  "query": {
    "has_child": {
      "type": "employee",
      "query": {
        "range": {
          "dob": {
            "gte": "1980-01-01"
          }
        }
      }
    }
  }
}

has_child 조회는 여러 개의 하위 문서와 일치하며, 문서마다 서로 다른 관련 득점이 있습니다.상위 문서의 개별 점수를 줄이는 방법은 분수 모델의 매개변수에 따라 다릅니다.기본 인자는 none입니다. 하위 문서의 점수를 무시하고 상위 문서는 1.0을 추가합니다.다음 조회는 런던과 리버풀을 동시에 되돌려주지만 런던은 더 좋은 점수를 얻을 수 있습니다. 앨리스 스미스가 런던과 더 일치하기 때문입니다.
GET /company/branch/_search
{
  "query": {
    "has_child": {
      "type":       "employee",
      "score_mode": "max",
      "query": {
        "match": {
          "name": "Alice Smith"
        }
      }
    }
  }
}

min_children and max_children


has_child와 filter 모두 min_children 및 max_children 두 개의 매개 변수는 하위 문서의 개수와 일치하는 부모 문서 데이터 아래의 조회를 되돌려주고 직원 두 명 이상의 지사를 되돌려주는 역할을 한다
GET /company/branch/_search
{
  "query": {
    "has_child": {
      "type":         "employee",
      "min_children": 2, 
      "query": {
        "match_all": {}
      }
    }
  }
}

Finding Children by Their Parents


nested 조회와 루트 노드 데이터만 되돌릴 수 있는 것과 달리 부모 문서와 하위 문서는 상대적으로 독립적이며 단독 조회가 가능하다,has_child 조회는 하위 문서에서 상위 문서로 돌아갈 수 있기 때문에has_parent 조회는 상위 문서에 따라 하위 문서와has_child 조회는 비슷합니다. 다음 조회는uk에서 일하는 직원들을 되돌려줍니다.
GET /company/employee/_search
{
  "query": {
    "has_parent": {
      "type": "branch", 
      "query": {
        "match": {
          "country": "UK"
        }
      }
    }
  }
}

has_parent 쿼리도 score_ 지원모드 모드, 그러나 none (기본값) 과 score 두 가지만 설정할 수 있습니다. 하위 문서마다 부모 문서만 가지고 있기 때문에 점수를 여러 하위 문서에 나누어 줄 필요가 없습니다. 이것은 단지 none 모드를 사용하느냐 score 모드를 사용하느냐에 달려 있습니다.

Children Aggregation


Parent-child 지원children aggregation
GET /company/branch/_search
{
  "size" : 0,
  "aggs": {
    "country": {
      "terms": { 
        "field": "country"
      },
      "aggs": {
        "employees": {
          "children": { 
            "type": "employee"
          },
          "aggs": {
            "hobby": {
              "terms": { 
                "field": "hobby"
              }
            }
          }
        }
      }
    }
  }
}

Grandparents and Grandchildren


parent-child 관계는 두 세대가 아니라 여러 세대의 관계를 가질 수 있지만 모든 관련 데이터는 같은shard로 나누어져야 한다.우리 는 이전 의 열 을 조금 수정하여county 를 branch 의 부 문서 로 만들었다
PUT /company
{
  "mappings": {
    "country": {},
    "branch": {
      "_parent": {
        "type": "country" 
      }
    },
    "employee": {
      "_parent": {
        "type": "branch" 
      }
    }
  }
}

Countries and branches는 단순한 부자 관계이기 때문에 우리는 같은 방식으로 색인 데이터를 만듭니다
POST /company/country/_bulk
{ "index": { "_id": "uk" }}
{ "name": "UK" }
{ "index": { "_id": "france" }}
{ "name": "France" }

POST /company/branch/_bulk
{ "index": { "_id": "london", "parent": "uk" }}
{ "name": "London Westmintster" }
{ "index": { "_id": "liverpool", "parent": "uk" }}
{ "name": "Liverpool Central" }
{ "index": { "_id": "paris", "parent": "france" }}
{ "name": "Champs Élysées" }

parent id는 모든 branch와 그들의 부모 문서가 같은shard에 분배되었다는 것을 보장합니다. 만약에 이전과 같다면,employee 데이터를 만듭니다. 무슨 일이 일어날까요?
PUT /company/employee/1?parent=london
{
  "name":  "Alice Smith",
  "dob":   "1970-10-24",
  "hobby": "hiking"
}

shard는 문서의 parent ID - london에 따라employee 문서를 분배하지만, 이 london 문서는 그의 parent id uk에 따라 분배되기 때문에employee 문서와country,branch는 다른shard에 분배될 가능성이 높다.그래서 모든 관련 문서가 같은shard에 분배될 수 있도록 추가 매개 변수routing이 필요합니다.
PUT /company/employee/1?parent=london&routing=uk 
{
  "name":  "Alice Smith",
  "dob":   "1970-10-24",
  "hobby": "hiking"
}

parent 매개 변수는 하위 문서와 부모 문서의 관련성에 사용됩니다.routing 매개 변수는 문서가 어느 shard에 분배되어 조회되고 집합되는지 확인하는 데 사용됩니다. 예를 들어 어떤 도시를 찾은 직원들이 하이킹을 좋아하는지 물었습니다.
GET /company/country/_search
{
  "query": {
    "has_child": {
      "type": "branch",
      "query": {
        "has_child": {
          "type": "employee",
          "query": {
            "match": {
              "hobby": "hiking"
            }
          }
        }
      }
    }
  }
}

좋은 웹페이지 즐겨찾기