使用活动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索引。