我有一个用户模型,其中有一个部门字段,其默认值为“工程”。
这个字段是在我们的网站上线两个月后推出的,而且由于它的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/
我认为我面临同样的问题。这有什么工作吗?我选择采用拔除,因为它不是内存密集型并节省时间。
答案 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')