[오늘의 배움] ElasticSearch Nested Query

이상민·2021년 5월 25일
0

[오늘의 배움]

목록 보기
54/70
post-thumbnail

발생 문제

리뷰 데이터에 검색 시 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"
        }
      },
      (... 생략 ...)

score_mode

자식 문서의 점수가 부모 문서의 점수에 어떻게 영향을 주는지도 설정할 수 있다. 기본값은 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

profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

0개의 댓글