質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

4385閲覧

railsで複数のカラムを一つの塊とみなし、複数のキーワードでAND検索したい

zendendo

総合スコア43

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2018/10/03 01:25

###実現したいこと
ruby(ruby on rails)でフォームオブジェクトを使い検索機能をつくっています。
複数のカラムを検索対象とし、
スペースで区切られた複数のキーワードに含むものを取得したいと考えています。

Itemモデルに、item_nameカラムとdescriptionカラムがあるとします。
ユーザーは「ノート 無地」というキーワードを入力したとき、
「ノート」「無地」というワードが含まれたレコードだけを取得します。

言い換えると・・・
item_nameカラムとdescriptionカラムの内容を一つの塊とみなし、
この塊(タイトル+説明文)で「ノート」と「無地」というワードが一緒にあれば取得(and検索)をしたい
のですが、
やり方が分からず困っています。
もし、知っている方がいましたら教えて頂ければ幸いです。

###現状のコード
現状のコードでは、
スペース入りの検索内容をスペースで区切って配列化して、
区切った検索内容ごとに検索をそれぞれのカラムで繰り返しています。

(Itemモデルitem_nameカラムで繰り返しor検索).or(Itemモデルdescriptionカラムで繰り返しor検索)
ただし、この場合だと検索ワードの一つに該当すれば取得されてしまい、2つの検索ワードがあるレコードだけを取得することはできません。

form/item_search_form.rb

ruby

1class ItemSearchForm 2 include ActiveModel::Model 3 attr_accessor :all_search 4 5 def search 6 result = Item.all 7 words = all_search.to_s.gsub(/(?:[[:space:]%_])+/, " ").split(" ") 8 query = (["item_name LIKE ?"] * words.size).join(" OR ") 9 query2 = (["description LIKE ?"] * words.size).join(" OR ") 10 11 result = result.where(query, *words.map{|w| "%#{w}%"}).or(ItemStock.where(query2, *words.map{|w| "%#{w}%"})).where(item_stock1_state: 1)#検索ワードがひとつでも含まれていれば取得される。一方でAND検索的な絞込取得はできない 12 result 13 14 end 15end

###環境
Rails 5.1.3
MySQL 5.6.39

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

■根本的な部分

というワードが一緒にあれば取得(and検索)をしたい

と言っているのに、全てをORで繋げたら目的を達成できないのは当然だと思います

■目的の構造と問題

word1検索(item_name or description) AND word2検索(item_name or description)

だと思われますが、そのためには
query = (["item_name LIKE ?"] * words.size).join(" OR ")
のように item_name を横並べしても実現できません

■実装例

目的の構造を把握した上でそれに合わせてループしましょう
また、クエリー文字列を組み上げるのはRails的ではありません
ActiveRecord:Relationを組み上げると良いでしょう

# 各ワードのORクエリを作る word_queries = words.map do |w| Item.where('item_name LIKE ?', "%#{w}%") .or(Item.where('description LIKE ?', "%#{w}%")) end # それらをAND条件で繋げる result = word_queries.inject(User) do |scope, query| scope.merge(query) end

投稿2018/10/03 03:19

Ighrs

総合スコア656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zendendo

2018/10/03 23:05

ighrsさん、丁寧な解説ありがとうございます。おかげで解決することができました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問