29
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

検索用Gem"SearchCop"の紹介

Railsで検索用のGemといえばRansackが有名かと思います。Ransackって多機能ですが独自のルールとかが多くて、しばらく使ってないと使い方忘れちゃう。

そこで、今回は別のシンプルな検索用GemであるSearchCopを使ってみたので紹介しようと思います。

特徴

Ransackでは独自の記法を用いて検索条件を組み立てますが、複数のフィールドに対して複数の検索ワードでAND検索やOR検索を実現するのは以外と大変です(以下は昔自分が書いた記事です)。

ransackを使った複数ワードによるAND検索の実装

SearchCopでは直感的かつ自然な書き方で、複雑な検索条件を組み立てることができます。

記述例

# 性・名・電話番号でのAND検索
User.search('田中 太郎 08012345678')

# メールアドレスに"gmail"が含まれており、登録が2015年あるいは2016年
User.search('email: gmail AND (created_at:2015 OR created_at:2016)')

サンプルコードで使うモデルの解説

例として、以下に示す二つのモデルが存在していると仮定します。

Userモデル

Userモデルは会員の情報を持つモデルで、以下のフィールドを含みます。

フィールド名
id integer
email string
first_name string
last_name string
age integer
created_at date
class User < ApplicationRecord
  has_many :posts
end

Postモデル

Postモデルは投稿内容を持つモデルで、以下のフィールドを含みます。

フィールド名
id integer
user_id integer
title string
message text
created_at date
class Post < ApplicationRecord
  belongs_to :user
end

UserPostは一対多の関係です。

使用方法

概要

仮に、Userに検索機能をつけたい場合、Userのモデルファイルに以下の記述を追加します。

class User < ApplicationRecord
  include SearchCop
  has_many :posts

  search_scope :search do
    attributes :email, :first_name, :last_name, :age, :created_at
    attributes post: ['posts.title', 'posts.message']
  end
end

上記のコードを追加することで、Userモデルでsearchというスコープが使えるようになります。

User.search('Ruby')

これだけの記述で、Userモデルの全フィールド及び関連テーブルであるPostモデルのフィールドに対して、"Ruby"という文字列でLIKE検索が走ります。

検索フィールドの指定

前述した例では全てのフィールドを指定しましたが、検索条件として特定のフィールドのみを指定することも可能です。また、検索スコープに名前を付けて、複数定義することもできます。

search_scope :name_search do
  attributes :first_name, :last_name, created_at
end

search_scope :post_search do
  attributes post: ['posts.title', 'posts.message']
end

検索時に検索対象のフィールドを指定することも可能です。ここで指定しない場合は、全フィールドが検索されます。

# last_nameのみを検索
User.search('last_name:松本')

日付や整数に対して、範囲指定することもできます。

# 2017年に登録されたもののみ
User.search('created_at:2017')

# ageが20より上
User.search('age > 20')

そして、これらの条件をANDやORで容易に組み合わせることもできます。

User.search('(last_name:松本 OR age > 20) AND created_at:2017')

FullText Indexへの対応

SearchCopはデフォルトでLIKE検索が実行されるため、レコード数やフィールドのサイズによっては、検索に時間がかかることが予想されます。

SearchCopでは、FullText Indexに標準で対応しています。

search_scope :search do
  attributes message: 'posts.message'
  options :message, type: :fulltext
end

ここでは、FullText Indexに関する詳細な説明は省きます(すみません、ここは試してないです・・・)。

終わりに

Ransackが、controllerやviewを含めた、サービスに組み込むための検索機能全般を提供しているのに対して、SearchCopはモデルを検索するためのインターフェースのみに特化ている感じでしょうか。controllerやview側の処理を自前で実装したい場合は、ベターな選択肢になるのではないでしょうか。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
29
Help us understand the problem. What are the problem?