2.X/4. Aggregations

4-10-5. Fielddata Filtering

drscg 2017. 9. 23. 22:27

Imagine that you are running a website that allows users to listen to their favorite songs. To make it easier for them to manage their music library, users can tag songs with whatever tags make sense to them. You will end up with a lot of tracks tagged with rockhiphop, and electronica, but also with some tracks tagged with my_16th_birthday_favorite_anthem.

사용자들이 각자가 좋아하는 노래를 들을 수 있는 website를 운영 중이라고 가정해 보자. 사용자들이 각자의 음악 라이브러리를 쉽게 관리하도록 하기 위해서, 그들이 원하는 어떠한 tag라도 노래에 달 수 있게 하였다. rockhiphopelectronica 등으로 tag된 많은 노래뿐만 아니라,my_16th_birthday_favourite_anthem(나의 16번째 생일에 매우 좋아했던 노래)이라고 tag된 곡도 보게 될 것이다.

Now imagine that you want to show users the most popular three tags for each song. It is highly likely that tags like rock will show up in the top three, but my_16th_birthday_favorite_anthem is very unlikely to make the grade. However, in order to calculate the most popular tags, you have been forced to load all of these one-off terms into memory.

이제 각 노래에 대해, 가장 인기를 끌고 있는 3개의 tag를, 사용자에게 보여 주려 한다고 가정해 보자. rock같은 tag는 상위 3개 안에 들 것이 확실하다. 그러나, my_16th_birthday_favourite_a-nthem 은 순위를 확인하기가 매우 어려울 것이다. 그러나 가장 인기를 끌고 있는 tag를 계산하기 위해, 이러한 일회성 단어 모두를 메모리에 로드 할 수 밖에 없다.

Thanks to fielddata filtering, we can take control of this situation. We know that we’re interested in only the most popular terms, so we can simply avoid loading any terms that fall into the less interesting long tail:

fielddata filtering 덕분에, 이 상황을 제어할 수 있다. 가장 인기있는 단어에만 관심이 있다는 것을 알기 때문에, 관심이 적은 불필요한 단어의 로드를 방지할 수 있다.

PUT /music/_mapping/song
{
  "properties": {
    "tag": {
      "type": "string",
      "fielddata": { 
        "filter": {
          "frequency": { 
            "min":              0.01, 
            "min_segment_size": 500  
          }
        }
      }
    }
  }
}

fielddata key는 이 field에 대해 fielddata를 다루는 방법을 설정한다.

frequency filter는 term frequency를 기반으로, fielddata 로드를 filtering한다.

이 segment에서 document 중 최소한 1% 이상 나타나는 단어만 로드

500개 이하의 document를 가지고 있는 segment는 무시

With this mapping in place, only terms that appear in at least 1% of the documents in that segmentwill be loaded into memory. You can also specify a max term frequency, which could be used to exclude terms that are too common, such as stopwords.

이 mapping이 준비가 되면, 해당 segment에서 document의 최소 1% 이상 나타나는 단어만 메모리에 로드 될 것이다. max term frequency를 지정할 수도 있는데, 이는 불용어처럼, 아주 흔한 단어를 제외하는데 사용될 수 있다.

Term frequencies, in this case, are calculated per segment. This is a limitation of the implementation: fielddata is loaded per segment, and at that point the only term frequencies that are visible are the frequencies for that segment. However, this limitation has interesting properties: it allows newly popular terms to rise to the top quickly.

이 경우에, term frequency는 segment별로 계산된다. 이것은 구현상의 한계이다. fielddata는 segment 별로 로드 되고, 그 시점에서 볼 수 있는 term frequency만이 해당 segment에 대한 빈도(frequency)이다. 그러나 이 제한은 재미있는 특성을 가지고 있다. 새로 인기를 끌고 얻는 단어는 빠르게 상위권으로 올라온다.

Let’s say that a new genre of song becomes popular one day. You would like to include the tag for this new genre in the most popular list, but if you were relying on term frequencies calculated across the whole index, you would have to wait for the new tag to become as popular as rock and electronica. Because of the way frequency filtering is implemented, the newly added tag will quickly show up as a high-frequency tag within new segments, so will quickly float to the top.

어느 날 새로운 장르의 노래가 인기를 끌고 있다고 가정해 보자. 가장 인기있는 목록에 이 새로운 장르에 대한 tag를 포함하고 싶지만, 전체 index에 대해 계산된 term frequency에 의존한다면, 새로운 tag가 rockelectronica 만큼 인기를 끌 때까지 기다려야 한다. frequency filtering 방식으로 구현되었기 때문에, 새롭게 추가된 tag는 새로운 segment내 높은 빈도의 tag로써, 빠르게 눈에 띄게 될 것이다. 따라서, 빠르게 상위권으로 떠오를 것이다.

The min_segment_size parameter tells Elasticsearch to ignore segments below a certain size. If a segment holds only a few documents, the term frequencies are too coarse to have any meaning. Small segments will soon be merged into bigger segments, which will then be big enough to take into account.

min_segment_size 매개변수는 특정 크기 이하의 segment를 무시하도록 한다. segment가 소수의 document만을 가지고 있다면, term frequency는 어떤 의미를 가지기에는 너무 조잡하다. 작은 segment가 더 큰 segment에 곧 병합되면, 의미를 가지기에 충분하게 될 것이다.

Tip

Filtering terms by frequency is not the only option. You can also decide to load only those terms that match a regular expression. For instance, you could use a regex filter on tweets to load only hashtags into memory — terms the start with a #. This assumes that you are using an analyzer that preserves punctuation, like the whitespaceanalyzer.

frequency로 단어를 filtering하는 것 외에도 옵션이 있다. 정규식에 일치하는 해당 단어만을 로드할 수도 있다. 예를 들어, hashtag(# 으로 시작하는 단어)만을 메모리에 로드 하기 위해, tweets에 regex filter를 사용할 수 있다. 이것은 whitespace analyzer 같은, 구두점(punctuation)을 유지하는 analyzer를 사용한다고 가정한 것이다.

Fielddata filtering can have a massive impact on memory usage. The trade-off is fairly obvious: you are essentially ignoring data. But for many applications, the trade-off is reasonable since the data is not being used anyway. The memory savings is often more important than including a large and relatively useless long tail of terms.

fielddata filtering은 메모리 사용에 막대한 영향을 끼칠 수 있다. trade-off는 매우 알기 쉽다. 여러분은 본질적으로 데이터를 무시하고 있다. 하지만, 많은 응용프로그램에서, 데이터는 어쨌든 사용되지 않고 있기 때문에, trade-off는 합리적이다. 메모리의 절약은 큰 그리고 상대적으로 쓸모 없는 단어를 포함하는 것보다 더 중요하다.

'2.X > 4. Aggregations' 카테고리의 다른 글

4-10-3. Aggregations and Analysis  (0) 2017.09.23
4-10-4. Limiting Memory Usage  (0) 2017.09.23
4-10-6. Preloading Fielddata  (0) 2017.09.23
4-10-7. Preventing Combinatorial Explosions  (0) 2017.09.23
4-11. Closing Thoughts  (0) 2017.09.23