elasticsearch-rails を導入して単純な検索までは簡単に実装できたのですが、階層化されたドキュメントのAND検索をする方法がなかなかでてこなかったのでメモ。
class Article
include Elasticsearch::Model
belongs_to :genre
# こんな感じで階層化されたドキュメントが登録されるようにする
def as_indexed_json(options = {})
as_json(
only: [:title, :content],
include: {
genre: {only: :name}
})
end
# 各フィールドをまたいでAND検索
def multi_field_search
query = {query:
{
multi_match: {
query: query,
type: 'cross_fields',
fields: %w[title content genre.name],
operator: 'and'
}
}
}
Article.search(query).records
end
end
ポイントは以下の2つ
-
multi_match
を使う -
type
に 'cross_fields' を指定する
multi_matchでfieldsに複数のフィールドを指定することができるようになります。fieldsパラメータではgenre.name
のようにドット区切りにして下層のフィールドを指定できます。
これだけですと、AND検索が単一フィールド内でしか行われないため、複数のワードが別々のフィールドに格納されているとマッチしません。そこでtype
にcross_fields
を設定すると、フィールドをまたいでAND検索できるようになります。