-
Join QueryBackEnd/Elasticsearch API 2025. 3. 29. 03:00반응형
Elasticsearch에서 JOIN은 문서 간의 관계를 설정하고 이를 통해 문서를 연결하여 검색할 수 있는 기능입니다. 단, Elasticsearch의 JOIN은 RDBMS와 달리 성능에 영향을 미칠 수 있습니다. 특히, has_child or has_parent 쿼리는 성능에 부담을 줄 수 있으므로, 데이터 모델링 시 신중히 고려해야 합니다.
Parent-Child 관계
Parent-Child 관계는 한 문서가 부모가 되고, 다른 문서가 자식이 되는 구조입니다. 이 관계는 인덱스 내에서 설정되며, 부모와 자식 문서는 반드시 같은 샤드에 저장되어야 합니다.
- has_child 쿼리: 자식 문서가 특정 조건을 만족할 때 부모 문서를 반환합니다.
- has_parent 쿼리: 부모 문서가 특정 조건을 만족할 때 자식 문서를 반환합니다.
Join 데이터 타입
Elasticsearch 6.x부터는 Join 데이터 타입을 사용하여 Parent-Child 관계를 설정할 수 있습니다. 이 타입은 문서 내에서 가능한 관계 집합을 정의하며, 각 관계는 부모 이름과 자식 이름으로 구성됩니다.
다음 library 인덱스는 부모(author)-자식(book) 관계를 가집니다.
PUT /library { "mappings": { "properties": { "my_join_field": { "type": "join", "relations": { "author": "book" // Define 'author' as parent and 'book' as child } }, "name": { "type": "text" }, // Common field for names "title": { "type": "text" }, // Field for book titles "genre": { "type": "keyword" }, // Field for book genres "year": { "type": "integer" } // Field for publication year } } }
부모 Documents를 생성합니다.
POST /library/_doc/1 { "my_join_field": "author", // Indicating this is a parent document "name": "J.K. Rowling" } POST /library/_doc/2 { "my_join_field": "author", // Indicating this is a parent document "name": "George R.R. Martin" }
자식 Documents를 생성합니다. 부모와 자식 문서는 반드시 같은 샤드에 저장되어야 하기 때문에 부모 문서의 ID를 자식 문서의 routing 값으로 사용합니다. (Elasticsearch에서 문서를 저장할 때 기본적으로 문서의 ID를 해싱하여 샤드를 결정합니다. 그러므로 부모 문서를 저장할 때는 별도의 라우팅 값을 지정하지 않아도 됩니다.)
POST /library/_doc/3?routing=1 { "my_join_field": { "name": "book", "parent": "1" // Link to the parent author (J.K. Rowling) }, "title": "Harry Potter and the Philosopher's Stone", "genre": "Fantasy", "year": 1997 } POST /library/_doc/4?routing=1 { "my_join_field": { "name": "book", "parent": "1" // Link to the parent author (J.K. Rowling) }, "title": "Harry Potter and the Chamber of Secrets", "genre": "Fantasy", "year": 1998 } POST /library/_doc/5?routing=2 { "my_join_field": { "name": "book", "parent": "2" // Link to the parent author (George R.R. Martin) }, "title": "A Game of Thrones", "genre": "Fantasy", "year": 1996 } POST /library/_doc/6?routing=2 { "my_join_field": { "name": "book", "parent": "2" // Link to the parent author (George R.R. Martin) }, "title": "A Clash of Kings", "genre": "Fantasy", "year": 1998 }
has_parent 쿼리
GET /library/_search { "query": { "has_parent": { "parent_type": "author", "query": { "match": { "name": "J.K. Rowling" } } } } }
has_child 쿼리
GET /library/_search { "query": { "has_child": { "type": "book", "query": { "match": { "title": "Game" } } } } } GET /library/_search { "query": { "has_child": { "type": "book", "query": { "term": { "genre": "Fantasy" } } } } }
Parent ID로 Child 문서 검색
GET /library/_search { "query": { "parent_id": { "type": "book", "id": 1 } } }
Inner Hit
GET /library/_search { "query": { "has_parent": { "inner_hits": {}, "parent_type": "author", "query": { "match": { "name": "J.K. Rowling" } } } } } GET /library/_search { "query": { "has_child": { "inner_hits": {}, "type": "book", "query": { "match": { "title": "Game" } } } } }
[참고자료]
반응형'BackEnd > Elasticsearch API' 카테고리의 다른 글
Proximity Search (0) 2025.03.31 Aggregation (0) 2025.03.30 Nested Query (0) 2025.03.23 Boosting (0) 2025.03.23 Full Text Search (0) 2025.03.22