elasticsearchで複雑なクエリーを組み立てる
背景
“railsから全文検索エンジンelasticsearchを利用する"では、全文検索を手軽に実装することを目的としていたので、検索クエリーの組み立てにはあまり踏み込んでいませんでした。
今回は複数のOR, AND条件の組み合わせなどを設定したい場合の記述方法を説明します。
bool query
elasticsearchには複雑なクエリーを組み立てるためのbool queryという仕組みが用意されています。
bool queryではmust
, should
, must_not
の組み合わせで表現を行います。
must
は必ず満たすべき条件を、should
は少なくとも満たす条件を、must_not
は満たしてはならない条件を指定します。
tireでの記述例
tireでの記述例を示します。
class Article < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
# ~中略~
def self.search(params)
tire.search(load: true) do
query {
boolean do
should { string 'tags:ruby' }
should { string 'tags:java' }
must_not { string 'tags:python' }
end
}
end
end
end
上記の例の場合、tags:ruby OR tags:java AND NOT tags:python
と指定していることになります。
boolクエリーの拡張
複数のboolクエリーを組み合わせる場合、各条件をブロックでまとめ、見通しを良くすることも可能です。
tags_query = lambda do |boolean|
boolean.should { string 'tags:ruby' }
boolean.should { string 'tags:java' }
end
published_on_query = lambda do |boolean|
boolean.must { string 'published_on:[2011-01-01 TO 2011-01-02]' }
end
class Article < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
# ~中略~
def self.search(params)
tire.search(load: true) do
query {
boolean &tags_query
boolean &published_on_query
}
end
end
end
boolクエリーにおけるshouldのオプション
boolクエリーではshould
の最小数一致数を指定することも可能です。
elasticsearchではminimum_should_matchパラメータで指定しますが、tireではminimum_number_should_match
での指定なので若干注意が必要です。
class Article < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
# ~中略~
def self.search(params)
tire.search(load: true, per_page: params[:per_page] ) do
query {
boolean(minimum_number_should_match: 1) do
Array(params[:cc]).each {|c| should { string 'curriculums:' + c}}
Array(params[:jc]).each {|j| should { string 'job_categories:' + j}}
end
boolean do
must {string 'school_code:' + params[:school_code] }
end
}
sort {
by :sort_key, :asc
}
end
end
end