mongoid pluck - 不使用模型中的默认值返回正确的值

时间:2016-04-01 10:16:39

标签: ruby-on-rails mongoid

我有一个用户模型,其中有一个部门字段,其默认值为“工程”。

这个字段是在我们的网站上线两个月后推出的,而且由于它的mongo,没有迁移。

当我尝试使用where获取对象时,返回正确的值

 User.find_by(:name => "John).department

但是,如果我尝试提取值,则返回nil而不是默认值。

 User.limit(2).pluck(:department)

返回

[nil,"Finance"]

我研究了一下,发现了这篇博文http://ahmadsherif.com/blog/2013/01/29/mongoid-default-fields-can-give-you-hard-time/

我认为我面临同样的问题。这有什么工作吗?我选择采用拔除,因为它不是内存密集型并节省时间。

1 个答案:

答案 0 :(得分:1)

基本上,这里的行为可以通过MongoDB处理默认值与传统关系数据库(如Postgres)的区别来解释。

在SQL世界中,您通过数据库模式设置默认值,每次插入行时,DB都将填充NULL字段。

由于MongoDB是无模式文档字段的默认值为nil,因为没有可以在数据库级别定义默认值的模式,因此无法更改*。而是在应用程序级别实现默认值。对于Mongoid,这意味着当您初始化新模型实例时,如果它们为零,则将填充默认值。

在ActiveRecord术语中,它看起来像这样:

class Thing < ActiveRecord::Base
  after_initialize :set_default_foo, if: -> { self.foo.nil? }

  private 
    def set_default_foo
      self.foo = "bar"
    end
end

但是,如果您有现有文档并添加新字段或默认为现有字段,则Mongoid不会为您更新现有文档!

那么这如何解释这两种情况呢?

User.find_by(:name => "John").department
User.limit(2).pluck(:department)

在第一种情况下,您将文档从存储中拉出并使用它来初始化模型实例。初始化模型实例时,将运行一个设置默认值的回调。

当手上调用.pluck时,Mongoid直接从商店中提取值而不初始化任何模型实例。因此,对于任何“遗留”文档,它将返回零值。

要解决此问题,您需要为nil设置任何文档的默认值。

User.where(department: nil).update_all(department: 'engineering')