Rails
Elastic Search
好簡單

+

 About Me

柯秉承

(科科, RichKe)

 

commandp 我印 資深工程師

 

Blog:http://blog.irich.im

Githug:https://github.com/run26kimo

 

 

 

Skill

Introduction

  • 什麼是 Elastic Search ?
  • 安裝 Elastic Search ( Mac 環境 )
  • 如何讓 Rails + Elastic Search 快速上手 ?

什麼是 Elastic Search ?

  • Apache 2 Open Source License
  • Distributed, scalable, and highly available
  • Real-time search and analytics capabilities
  • RESTful API
  • Full-Text Search

Elastic Search Use Case

安裝 Elastic Search ( Mac 環境 )

   方法一 : 使用 homebrew

$ brew install elasticsearch

安裝 Elastic Search ( Mac 環境 )

   方法二 : Docker

$ Install docker, https://docs.docker.com/engine/installation/mac/
$ mkdir docker_elasticsearch_2_1_2
$ cd docker_elasticsearch_2_1_2
$ vim docker-compose.yml
$ docker-compose up
# docker-compose.yml
version: '2'
services:
  elasticsearch:
    image: elasticsearch:2.1.2
    ports:
     - "9201:9200"
     - "9301:9300"
    volumes:
     - "$PWD/esdata/plugins:/usr/share/elasticsearch/plugins"
     - "$PWD/esdata:/usr/share/elasticsearch/data"

下一頁

Install  elastic search plugin head

$ open a new terminal
$ cd docker_elasticsearch_2_1_2
$ docker ps, get CONTAINER ID
$ docker exec CONTAINER ID /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head

 WTF都裝不起來!

直接註冊

www.searchly.com

取得一串 host

https://site:c56fxxxxxxx7ee50c0253362a581@dori-us-east-1.searchly.com

如何讓 Rails
+
Elastic Search
快速上手 ?

gem "searchkick"

有啥優點

  • 不需要了解 elastic search 語法
  • 與 elstic 官方的 elasticsearch-rails 相比
    • 更快速上手 
    • 設定更簡單
  • 支援
    • Suggestions
    • Aggregations
    • Analytics (with Searchjoy)
    • heiglight
    • more ...

Searchkick get started

#Gemfile
gem 'searchkick'

add gem

add search to model

class Product < ActiveRecord::Base
  searchkick
end

這樣已經開始 Rails + elasticsearch

setting elastic search host

#/config/initializers/elasticsearch.rb
host = 'localhost:9201'
Searchkick.client = Elasticsearch::Client.new(hosts: [host], 
                                              retry_on_failure: true)

add data to search index

# rails console
> Product.reindex
>
> products = Product.search('apple')
> products.each { |product| puts product.name }

自訂 搜尋資料

class Product < ActiveRecord::Base
  searchkick
  belongs_to :category

  #解決 reindex n+1 query
  scope :search_import, -> { includes(:category) }

  #自訂搜尋資料
  def search_data
    {
      name: name,
      category_name: category.name,
      desc: desc
    }
  end
end

Queries

# 指定 published = true
Product.search "apples", where: {published: true}, limit: 10, offset: 50

# 指定 搜尋欄位 name, category_name
Product.search "apples", fields: [:name, :category_name]

# where
where: {
  expires_at: {gt: Time.now}, # lt, gte, lte also available
  orders_count: 1..10,        # equivalent to {gte: 1, lte: 10}
  aisle_id: [25, 30],         # in
  store_id: {not: 2},         # not
  aisle_id: {not: [25, 30]},  # not in
  user_ids: {all: [1, 3]},    # all elements in array
  category: /frozen .+/,      # regexp
  or: [
    [{in_stock: true}, {backordered: true}]
  ]
}

# 排序
order: {_score: :desc}

# page
page: params[:page], per_page: 10

Results

results = Product.search("apple")

# 回傳結果總數
results.size
results.total_count

# 有沒有搜尋到資料
results.any?

# 列出搜尋結果
results.each { |result| ... }

# 搜尋時間
results.took

# 取得 elastic search response
results.response

Synonyms 同義字

class Product < ActiveRecord::Base
  synonyms: [["apple", "蘋果"], ["asus", "華碩"]]
  # or
  # searchkick synonyms: -> { CSV.read("/some/path/synonyms.csv") }
end

Suggestions 建議字

class Product < ActiveRecord::Base
  searchkick suggest: [:name]
end



products = Product.search "applg", suggest: true
products.suggestions # ["apple"]
products = Product.search "apple", aggs: [:category_name]
products.aggs

#results
{
  "category_name": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "DC",
        "doc_count": 3
      },
      {
        "key": "Phone",
        "doc_count": 2
      },
      {
        "key": "Watch",
        "doc_count": 2
      }
    ]
  }
}
class Product < ActiveRecord::Base
  searchkick highlight: [:name, :desc]
end



products = Product.search "apple", highlight: true

# 自訂 tag
products = Product.search "apple", highlight: { tag: "<mark>" }


products.with_details.each do |products, details|
  puts details[:highlight][:name] # "<mark>Apple</mark> Norma Cole"
end

Analytics

with Searchjoy

Product.search "apple", track: { user_id: current_user.id }

Demo

Github

Thank You

Rails + Elastic Search 好簡單

By Rich Ke

Rails + Elastic Search 好簡單

介紹 Rails 使用 gem 'searchkick',讓 Rails + Elastic Search 快速整合

  • 1,609