리뷰 데이터에 검색 시 relevance 점수가 매우 낮게 측정된다
책 인덱스에 데이터가 아래와 같이 동적 매핑을 통해 매핑 되었다
"mappings" : {
"properties" : {
"author" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"book_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"description" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"genre" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"reviews" : {
"properties" : {
"rating" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"review" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"title" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
순서도 제멋대로 들어가서 읽기 불편할뿐더러 가장 큰 문제는 review에 대해서 검색할때였다. 단순히 match 검색시 리뷰 데이터에서 복붙한 문장을 넣어도 relevance score가 0.007 같이 터무니 없이 낮게 나왔다.
자식 문서에 대해 nested type 미설정
nested type으로 들어가지 않고 단순 object로 들어가니 reviews.review 데이터가 하나의 배열로 flatten 되었다. 그때문에 검색 시 책의 리뷰 데이터 각각이 아닌 권당 250여건에 달하는 리뷰 데이터 전체에 검색을 하니 점수가 처참할 수 밖에 없었다...
명시적 맵핑과 nested query
mapping을 직접 짜서 reviews 필드가 nested type이 되도록 설정했다.
PUT /book
{
"mappings" : {
"properties" : {
"book_id" : {"type" : "long"},
"title" : {"type" : "text"},
"author" : {"type": "text"},
"genre" : {"type": "text"},
"description" : {"type": "text"},
"reviews" : {
"type" : "nested",
"properties": {
"rating" : {"type" : "integer"},
"review" : {"type" : "text"}
}
}
}
}
}
이후 nested query로 검색했다
GET /book/_search
{
"_source": ["title", "author", "genre"],
"query": {
"nested": {
"path": "reviews",
"query": {
"match": {
"reviews.review": "book about totalitarian regime"
}
}
}
}
}
결과
{
"took" : 57,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 97,
"relation" : "eq"
},
"max_score" : 2.5575206,
"hits" : [
{
"_index" : "book",
"_type" : "_doc",
"_id" : "63",
"_score" : 2.5575206,
"_source" : {
"author" : "George Orwell",
"genre" : [
"Classics",
"Fiction",
"Science Fiction",
"Science Fiction",
"Dystopia",
"Literature",
"Novels",
"Politics",
"Academic",
"School",
"Fantasy",
"Adult"
],
"title" : "1984"
}
},
(... 생략 ...)
자식 문서의 점수가 부모 문서의 점수에 어떻게 영향을 주는지도 설정할 수 있다. 기본값은 avg로 검색에 매칭되는 자식 문서들의 점수 평균을 사용한다. 이외에도 max, min, none, sum이 가능하다. 자세한 설명은 참조의 Nested query 참고
Difference about the “nested” type and “object” type?
https://discuss.elastic.co/t/difference-about-the-nested-type-and-object-type/15374
Nested query
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html