使用活动记录搜索序列化数据

JZ.*_*JZ. 46 search serialization activerecord ruby-on-rails

我正在尝试对序列化列进行简单查询,你是如何做到这一点的?

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)
 => [] 
Run Code Online (Sandbox Code Playgroud)

rks*_*rks 72

这只是一个不会减慢你的应用程序速度的技巧.你必须使用.to_yaml.

确切结果:

MyModel.where("mycode = ?", [43565, 43402].to_yaml)
#=> [#<MyModel id:...]
Run Code Online (Sandbox Code Playgroud)

仅针对MySQL进行测试.

  • 也适用于Postgres,至少,我能够找到具有空序列化字段foo的对象:where("foo =?",{}.to_yaml).last (4认同)
  • 这仅适用于完全匹配.如果你使用`MyModel.where("mycode LIKE?","%#{[43565,43402] .to_yaml}%")`它也适用于部分匹配. (3认同)

noo*_*odl 38

基本上,你不能.#serialize的缺点是你绕过了数据库的本机抽象.您几乎只能加载和保存数据.

也就是说,减慢应用程序爬行速度的一个非常好的方法可能是:

MyModel.all.select { |m| m.mycode.include? 43402 }
Run Code Online (Sandbox Code Playgroud)

故事的道德:不要将#serialize用于您需要查询的任何数据.

  • 这不再是真的.对于大多数Rails 4应用程序,基本上,你可以.有关详细信息,请参阅konung的答案和我的答案. (6认同)
  • 不得不哈哈这个答案,这是我最好的减速方法之一:) (5认同)
  • 确保查看该线程上的其他答案 (2认同)

jbm*_*yid 33

序列化数组以特定方式存储在数据库中,例如:

[1, 2, 3, 4]
in
1\n 2\n 3\n etc
Run Code Online (Sandbox Code Playgroud)

因此查询将是

MyModel.where("mycode like ?", "% 2\n%")
Run Code Online (Sandbox Code Playgroud)

把空间放在%和之间2.

  • 如果你有两个值,比如 "0597841" 和 "1597841",它只能找到一个,因为 `"0597841".to_yaml #=&gt; "--- 0597841\n...\n"` 和 `"1597841".to_yaml #=&gt; "--- '1597841'\n"` 完全不同的格式。因此,我不喜欢 `to_yaml` 和序列化数据。 (2认同)

kon*_*ung 17

Noodl的回答是对的,但并不完全正确.

这实际上取决于您使用的数据库/ ORM适配器:例如,PostgreSQL现在可以存储和搜索哈希/ json - 请查看hstore.我记得读过PostgreSQl的ActiveRecord适配器现在正确处理它.如果您正在使用mongoid或类似的东西 - 那么您在数据库级别上使用非结构化数据(即json).

但是,如果您使用的数据库无法真正处理哈希 - 例如MySQL/ActiveRecord组合 - 那么您使用序列化字段的唯一原因是您可以在某些后台进程中创建/写入以及按需显示/输出的某些数据 - 我在经验中发现的唯一两个用途是一些报告(比如产品型号上的统计字段 - 我需要存储产品的一些平均值和中位数),以及用户选项(比如他们喜欢的模板颜色 - 我真的不需要查询 - 但是用户信息 - 比如他们对邮件列表的订阅 - 需要可以搜索电子邮件爆炸.

PostgreSQL hstoreActiveRecord示例:

MyModel.where("mycode @> 'KEY=>\"#{VALUE}\"'")
Run Code Online (Sandbox Code Playgroud)

更新 截至2017年,MariaDB和MySQL都支持JSON字段类型.


Nea*_*JMD 8

好消息!如果您将PostgreSQL与hstore一起使用(使用Rails 4非常简单),您现在可以完全搜索序列化数据.是一个方便的指南,和这里的从PG语法文档.

在我的例子中,我将一个字典存储为hstore列中的哈希值amenities.我想查看一些具有1哈希值的查询设施,我就是这样做的

House.where("amenities @> 'wifi => 1' AND amenities @> 'pool => 1'")
Run Code Online (Sandbox Code Playgroud)

万岁改善!


Kyl*_*e C 7

您可以使用sql LIKE语句查询序列化列.

 MyModel.where("mycode LIKE '%?%'", 43402)
Run Code Online (Sandbox Code Playgroud)

这比使用include?更快,但是,您不能使用数组作为参数.

  • 这个问题是它也会匹配像143402或434020这样的记录.如果你想使用`LIKE',你最好使用像jbmyid上面的答案. (2认同)