옛글/Ruby on the Rails

[Ruby on rails] ElasticSearch 를 붙여보자

ShakeJ 2017. 4. 14. 12:18

검색을 위한 ElasticSearch를 Rails에 붙여봅시다. 


ElasticSearch이 무엇이며 왜 사용해야 하는지부터 알아봅시다. 

(https://www.elastic.co)


! 설치와 실행이 간편하다

! ElasticSearch는 Java기반으로 빠른 검색이 가능하다.

! Lucene Libarary를 사용하여 Restful 방식으로 검색이 가능하다 

! CSV, XML, JSON 등 다양한 포맷을 지원한다. 

! Multi-tenancy 를 지원하여 여러개의 Index에 한번에 질의가 가능하다.


한 마디로 검증이 되어 있는 검색엔진이기에 서비스에 "검색"을 붙일 때 해당 엔진을 사용하여 좀 더 빠르고 쉽게 검색이 가능하다는 장점이 있습니다. 

데이터베이스에 직접적으로 쿼리로 검색을 하는 것이 아닌, ElasticSearch엔진에서 Indexing을 하고 있다가 검색에 대한 결과를 제공하기 때문에 데이터베이스의 부담은 낮아지게 됩니다. (물론 엔진이 도는 서버 리소스의 부담은 있지만)


ElasticSearch 알고리즘은 아래 Speaker Deck을 참고하시기 바랍니다. 




자 ubuntu에 설치를 해봅시다. (AWS / Azure 에서 RDS형태로도 제공을 해줍니다)


sudo add-apt-repository -y ppa:webupd8team/java

sudo apt-get update

sudo apt-get -y install oracle-java8-installer

java -version

wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-2.2.0.deb

sudo dpkg -i elasticsearch-2.2.0.deb

service elasticsearch start


이렇게 설치 후 실행을 시키면, Rails model에 ElasticSearch를 사용하기 위해 적힌 모델들에 대해서 Indexing을 하게 됩니다.

모델 클래스를 수정해봅시다.


Gemfile


gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git' gem 'elasticsearch-rails', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'


Message.rb (Model)


class Message < ApplicationRecord

  include Elasticsearch::Model

  include Elasticsearch::Model::Callbacks

end

Message.import force: true


이제 ElasticSearch를 재 실행하게 되면, 


알아서 맵핑을 하게 됩니다.


간단하게 쿼리를 날려 검색을 해보겠습니다.


Message.rb


def self.search(query, chat_ids)

    search_definition =

    {

      query: {

        bool: { filter: {

                 terms: {

                   "chat_id": chat_ids,

                 },

              },

              must: {

                  multi_match: {

                    "query": query,

                    "type": "phrase_prefix",

                    "fields": [ "body" ],

                    }

                  }

              },

      }

    }

    __elasticsearch__.search(search_definition)

  end


검색을 할 때 query가 body 컬럼에 필수로 포함되어 있어야 하며, 특정 채팅방 id들 안에서만 필터링하여 검색을 하라라고 구현을 했습니다.

메세지들을 검색할 때에는 Message.search("TEST", chat_ids)로 해당 메서드를 호출하면 ElasticSearch에서 결과를 리턴해줍니다.



데이터베이스에서 쿼리를 던지면 나오는 Relation과는 다르게 ElasticSearch의 모델로 결과가 튀어나오게 됩니다. 


결과를 가져오기 위해서는,


search_result = Message.search("Test", chat_ids)

result = search_result.result.to_a


로 사용을 하면, 검색 결과로 나온 Message 모델들의 Array 형태로 사용이 가능합니다. 


기본적인 설치법과 사용법입니다. 혹시라도 추후에 추가적인 기능적인 사용이나 이슈가 있으면 한 번 더 공유하겠습니다 :)