Join 필드 타입
Join 필드 타입
join 필드 타입은 같은 인덱스 안의 문서들 사이에 부모/자식 관계를 정의해요. 쿼리가 관련 문서를 연결할 수 있도록 문서들이 어떻게 관련되어 있는지 기록하는 다음 작업을 수행해요.
- 관계 이름 정의: 부모와 자식 타입의 이름을 지정해요(예:
brand와product). - 관계 메타데이터 저장: 어떤 문서가 부모이고 어떤 문서가 자식이며 어떻게 연결되는지 식별해요.
- 부모/자식 쿼리 지원: 자식으로 부모를 찾거나 부모로 자식을 찾는 join 쿼리를 지원해요.
출처: 문서
본문
예시
다음 예시에서는 브랜드가 부모이고 제품이 자식인 인덱스를 만들어요.
1단계: 매핑 만들기
제품과 브랜드 사이에 부모/자식 관계를 설정하는 매핑을 만들어 볼게요. name 필드는 제품 또는 브랜드 이름을 저장해요. product_to_brand 필드는 "brand": "product" 관계를 정의하는 join 필드로, 브랜드 문서가 제품 자식을 가질 수 있음을 나타내요.
PUT testindex1
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"product_to_brand": {
"type": "join",
"relations": {
"brand": "product"
}
}
}
}
}
2단계: 부모 문서(브랜드) 색인
브랜드를 나타내는 부모 문서를 색인하고, product_to_brand 필드에서 부모/자식 관계에서의 역할("brand")을 정의해요.
PUT testindex1/_doc/1
{
"name": "Brand 1",
"product_to_brand": {
"name": "brand"
}
}
객체 표기법 없이 줄여서 부모 문서를 색인할 수도 있어요.
PUT testindex1/_doc/1
{
"name": "Brand 1",
"product_to_brand" : "brand"
}
3단계: 자식 문서(제품) 색인
자식 문서를 색인할 때는 routing 쿼리 파라미터를 지정해야 해요. 같은 부모/자식 계층에 있는 부모·자식 문서는 같은 샤드에 색인되어야 하기 때문이에요. 자세한 내용은 Routing 문서를 참고하세요.
각 자식 문서는 join 필드의 parent 필드에서 부모의 ID를 참조해요.
제품을 나타내는 자식 문서 두 개를 색인해 볼게요. 각 문서의 부모/자식 관계 역할("product")을 product_to_brand 필드에 정의하고, ID가 1인 브랜드에 속한다는 것을 지정해요.
PUT testindex1/_doc/3?routing=1
{
"name": "Product 1",
"product_to_brand": {
"name": "product",
"parent": "1"
}
}
PUT testindex1/_doc/4?routing=1
{
"name": "Product 2",
"product_to_brand": {
"name": "product",
"parent": "1"
}
}
이 단계가 끝나면 인덱스에는 이 구조의 문서 세 개가 들어 있어요.
| 문서 ID | 문서 타입 | name 필드 | product_to_brand 필드 |
|---|---|---|---|
| 1 | 부모 (brand) | "Brand 1" | {"name": "brand"} |
| 3 | 자식 (product) | "Product 1" | {"name": "product", "parent": "1"} |
| 4 | 자식 (product) | "Product 2" | {"name": "product", "parent": "1"} |
join 필드 쿼리
join 필드를 쿼리하면 응답에 반환된 문서가 부모인지 자식인지 지정하는 하위 필드가 포함돼요. 자식 객체의 경우 부모 ID도 함께 반환돼요.
모든 문서 검색
GET testindex1/_search
{
"query": {
"match_all": {}
}
}
응답은 문서가 부모인지 자식인지를 나타내요.
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "Brand 1",
"product_to_brand" : {
"name" : "brand"
}
}
},
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"name" : "Product 1",
"product_to_brand" : {
"name" : "product",
"parent" : "1"
}
}
},
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"name" : "Product 2",
"product_to_brand" : {
"name" : "product",
"parent" : "1"
}
}
}
]
}
}
부모의 모든 자식 검색
Brand 1과 연관된 모든 제품을 찾아볼게요.
GET testindex1/_search
{
"query" : {
"has_parent": {
"parent_type":"brand",
"query": {
"match" : {
"name": "Brand 1"
}
}
}
}
}
응답에는 Brand 1과 연관된 Product 1과 Product 2가 포함돼요.
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"name" : "Product 1",
"product_to_brand" : {
"name" : "product",
"parent" : "1"
}
}
},
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.0,
"_routing" : "1",
"_source" : {
"name" : "Product 2",
"product_to_brand" : {
"name" : "product",
"parent" : "1"
}
}
}
]
}
}
자식의 부모 검색
Product 1의 부모를 찾아볼게요.
GET testindex1/_search
{
"query" : {
"has_child": {
"type":"product",
"query": {
"match" : {
"name": "Product 1"
}
}
}
}
}
응답은 Brand 1을 Product 1의 부모로 반환해요.
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "testindex1",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "Brand 1",
"product_to_brand" : {
"name" : "brand"
}
}
}
]
}
}
자식이 많은 부모 (Parent with many children)
하나의 부모는 많은 자식을 가질 수 있어요. 여러 자식을 가진 매핑을 만들어 볼게요.
PUT testindex1
{
"mappings": {
"properties": {
"parent_to_child": {
"type": "join",
"relations": {
"parent": ["child 1", "child 2"]
}
}
}
}
}
join 필드 타입 참고 사항
- 인덱스에는 join 필드 매핑이 하나만 있을 수 있어요.
- 자식 문서를 검색, 업데이트, 삭제할 때는 routing 파라미터를 제공해야 해요. 같은 관계에 있는 부모·자식 문서는 같은 샤드에 색인되어야 하기 때문이에요.
- 여러 부모는 지원되지 않아요.
- 기존 문서가 이미 부모로 표시된 경우에만 그 문서에 자식 문서를 추가할 수 있어요.
- 기존 join 필드에 새 관계를 추가할 수 있어요.
다음 단계 (Next steps)
- join 필드에서의 조인 쿼리에 대해 알아보기.
- inner hits 검색에 대해 자세히 알아보기.