使用活动loggingsearch序列化的数据
我试图做一个序列化列的简单查询,你怎么做到这一点?
serialize :mycode, Array 1.9.3p125 :026 > MyModel.find(104).mycode MyModel Load (0.6ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`id` = 104 LIMIT 1 => [43565, 43402] 1.9.3p125 :027 > MyModel.find_all_by_mycode("[43402]") MyModel Load (0.7ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = '[43402]' => [] 1.9.3p125 :028 > MyModel.find_all_by_mycode(43402) MyModel Load (1.2ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = 43402 => [] 1.9.3p125 :029 > MyModel.find_all_by_mycode([43565, 43402]) MyModel Load (1.1ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` IN (43565, 43402) => []
基本上,你不能。 #serialize的缺点是你绕过了数据库的本地抽象。 你几乎无法加载和保存数据。
也就是说,减缓应用程序爬行的一个非常好的方法是:
MyModel.all.select { |m| m.mycode.include? 43402 }
道德故事:不要使用#serialize查询任何需要查询的数据。
这只是一个窍门,不要拖慢你的应用程序。 你必须使用.to_yaml
。
确切结果:
MyModel.where("mycode = ?", [43565, 43402].to_yaml) #=> [#<MyModel id:...]
仅针对MySQL进行testing。
序列化数组以特定方式存储在数据库中,例如:
[1, 2, 3, 4] in 1\n 2\n 3\n etc
因此查询将是
MyModel.where("mycode like ?", "% 2\n%")
把%
和2
之间的空间。
Noodl的答案是对的,但不完全正确。
这实际上取决于你正在使用的数据库/ ORM适配器:例如PostgreSQL现在可以存储和search散列/ json – 检出hstore。 我记得阅读PostgreSQl的ActiveRecord适配器现在可以正确处理它。 如果你正在使用mongoid或类似的东西 – 那么你到处使用数据库级别的非结构化数据(即JSON)。
但是,如果你使用的是一个不能真正处理哈希的数据库 – 比如MySQL / ActiveRecord的组合 – 那么你使用序列化字段的唯一原因就是可以在某些后台进程中创build/写入的一些数据,并根据需要显示/输出 – 根据我的经验,我发现只有两个用途是一些报告(例如产品模型上的统计字段 – 我需要存储产品的平均值和中位数)和用户选项(如他们喜欢的模板颜色 – 我真的不需要查询) – 但是用户信息 – 比如邮件列表的订阅 – 需要在电子邮件爆炸中search。
PostgreSQL
hstore
ActiveRecord示例:MyModel.where("mycode @> 'KEY=>\"#{VALUE}\"'")
好消息! 如果您使用PostgreSQL和hstore(这对于Rails 4来说非常容易),现在可以完全search序列化的数据。 这是一个方便的指南, 这里是PG的语法文档。
在我的情况下,我有一个字典作为散列存储在hstore列称为amenities
。 我想检查一些在哈希值为1
查询设施,我只是这样做
House.where("amenities @> 'wifi => 1' AND amenities @> 'pool => 1'")
万岁的改进!
您可以使用sql LIKE语句来查询序列化的列。
MyModel.where("mycode LIKE '%?%'", 43402)
这比使用include?更快,但是,不能使用数组作为参数。
FriendFeed在2009年发表了一篇博客文章 ,介绍如何在MySQL中使用序列化数据。
你可以做的是创build表作为任何你想要search的数据的索引。
创build一个包含可search的值/字段的模型
在你的例子中,模型看起来像这样:
class MyModel < ApplicationRecord # id, name, other fields... serialize :mycode, Array end class Item < ApplicationRecord # id, value... belongs_to :my_model end
为可search字段创build一个“索引”表
当你保存MyModel时,你可以做这样的事情来创build索引:
Item.where(my_model: self).destroy self.mycode.each do |mycode_item| Item.create(my_model: self, value: mycode_item) end
查询和search
那么当你想查询和search只是做:
Item.where(value: [43565, 43402]).all.map(&:my_model) Item.where(value: 43402).all.map(&:my_model)
你可以添加一个方法到MyModel来简化:
def find_by_mycode(value_or_values) Item.where(value: value_or_values).all.map(&my_model) end MyModel.find_by_mycode([43565, 43402]) MyModel.find_by_mycode(43402)
为了加快速度,您需要为该表创build一个SQL索引。