web-dev-qa-db-ja.com

配列に保存されているActiveRecordデータをクエリするにはどうすればよいですかRails

Railsモデル呼び出しMentorDataがあり、_os_usage_という属性があります。osesは_['Apple', 'linux']_のような配列に格納されます。

要点をまとめると:

_$ MentorData.first.os_usage
=> ['Apple',  'linux']
_

Appleのos_usageを含むすべてのMentorDataのデータをクエリできるようにしたいと思っていますが、MentorData.where(os_usage: 'Apple')を検索すると、AppleではなくAppleおよびlinux。Appleが配列に含まれているかどうかを確認する方法で検索する必要があります。

私も以下を試しました。

_MentorData.where('os_usage like ?', 'Apple’)
MentorData.where('os_usage contains ?', 'Apple’)
MentorData.where('os_usage contains @>ARRAY[?]', 'Apple')
_

配列またはアイテムを持つ属性によってActiveRecordのデータをクエリすることは可能ですか?

より生の検索クエリを提供するのに役立つ場合、データベースはPostgres上にあります。

13
bdougie

これが現在の Rails Edge Guides で与えられた例です:

# db/migrate/20140207133952_create_books.rb
create_table :books do |t|
  t.string 'title'
  t.string 'tags', array: true
  t.integer 'ratings', array: true
end
add_index :books, :tags, using: 'gin'
add_index :books, :ratings, using: 'gin'

# app/models/book.rb
class Book < ActiveRecord::Base
end

# Usage
Book.create title: "Brave New World",
            tags: ["fantasy", "fiction"],
            ratings: [4, 5]

## Books for a single tag
Book.where("'fantasy' = ANY (tags)")

## Books for multiple tags
Book.where("tags @> ARRAY[?]::varchar[]", ["fantasy", "fiction"])

## Books with 3 or more ratings
Book.where("array_length(ratings, 1) >= 3")
30
David Aldridge

MentorData.where("'Apple' = ANY (os_usage)")を試しましたか?

4
Zepplock

モデルからos_usage配列を切り離して、別のテーブルにする必要があるかもしれません。

ActiveRecordの世界では、次のようなコードが表示されます。

class MentorData < ActiveRecord::Base
  ..
  has_and_belongs_to_many :os_usage
  ..
end

class OsUsage < ActiveRecord::Base
  ..
  has_and_belongs_to_many :mentors_data
  ..
end

この2つのモデル間にmany_to_many関係を作成すると、クエリを簡単に実行して重複を回避できます。この手法は正規化と呼ばれます。

この新しいdesignを使用すると、文字列ではなくオブジェクトによって作成されたos_usageのコレクションが得られます。

MentorData.first.os_usage
# => [#<OsUsage:....>, #<OsUsage:...>]

簡単に古い文字列の配列に変換できます

MentorData.first.os_usage.map(&:name)
# => ['Apple',  'linux']

さらに、Appleのos_usageを含むすべてのMentorDataのデータをクエリできます。

MentorData.joins(:os_usages).where('os_usages.name' => 'Apple')

また、すべてのMentorDataレコードにOsUsageのクエリを実行します。

OsUsage.where(name: 'Apple').mentors_data

お役に立てば幸いです:)

1
emancu

同様のクエリの場合、検索の左側または右側にテキストを表示できることを示すために%%が必要です。

だから、試してみてください

MentorData.where('os_usage LIKE "%Apple%"')

それが機能するかどうかを確認します。

これはワイルドカード検索ですが、%を省略すると=のように動作します

この質問を参照してください: '='と同じワイルドカードのないSQLLIKE?

これはos_usageはシリアル化された配列であり、そのデータを裏付ける列は文字列であり、Rails MentorDataをインスタンス化するときに逆シリアル化されます

編集:あなたのデータベースがどのように配列を格納しているかを知るので、多分あなたはすることができます

"%'Apple'%"

名前にAppleが含まれているだけのosesを選択しないようにします。

0
NullVoxPopuli