我有一个rails模型调用MentorData,它有一个名为os_usage
的属性。 ose存储在类似['apple', 'linux']
的数组中。
回顾一下:
$ MentorData.first.os_usage
=> ['apple', 'linux']
我希望能够查询包含apple
的os_usage的所有MentorData的数据,但是当我搜索MentorData.where(os_usage: 'apple')
时,我只会得到只能使用苹果而不是苹果的导师Linux操作系统。我需要以某种方式搜索,检查数组中是否包含apple。
我也尝试了以下内容。
MentorData.where('os_usage like ?', 'apple’)
MentorData.where('os_usage contains ?', 'apple’)
MentorData.where('os_usage contains @>ARRAY[?]', 'apple')
是否可以通过具有数组或项目的属性查询ActiveRecord中的数据?
数据库位于Postgres上,如果这有助于提供更原始的搜索查询。
答案 0 :(得分:23)
以下是当前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")
答案 1 :(得分:3)
您是否尝试过MentorData.where("'apple' = ANY (os_usage)")
?
答案 2 :(得分:1)
也许您应该从模型中分离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
在这两个模型之间创建many_to_many
关系,可以让您轻松查询并避免重复。这种技术称为规范化。
使用这个新的设计,你有 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')
并查询OsUsage的所有MentorData记录:
OsUsage.where(name: 'apple').mentors_data
我希望你觉得它很有用:)
答案 3 :(得分:0)
对于类似的查询,您需要%%来指示文字可以显示在搜索的左侧或右侧。
所以,试试
MentorData.where('os_usage LIKE "%apple%"')
看看是否有效。
这是一个外卡搜索,但省略%操作就像=
请参阅此问题:SQL LIKE with no wildcards the same as '='?
这假设os_usage
是序列化数组,其中支持该数据的列是字符串,并且在实例化MentorData
编辑:我发现你的数据库是如何存储数组的,所以也许你可以做到
"%'apple'%"
确保它不会选择名称中包含苹果的ose。