添加具有 nil 值的新动态属性

Posted

技术标签:

【中文标题】添加具有 nil 值的新动态属性【英文标题】:Add new dynamic attribute with nil value 【发布时间】:2021-01-15 06:03:26 【问题描述】:

我在向 mongoid 文档添加新的动态属性时遇到问题,其值为 nil

class User
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Attributes::Dynamic
end
u = User.find(id)
u.write_attribute(:bar, nil)
puts u.bar
# => nil
u.save!

u = User.find(id)
puts u.bar
# => NoMethodError (undefined method `bar for #<User:0x00007fe87a97cfd8>)

添加具有除nil 以外的任何其他值的新属性都可以正常工作。

u = User.find(id)
u.write_attribute(:foo, "a")
puts u.foo
# => "a"
u.save!

u = User.find(id)
puts u.foo
# => "a"

这里有什么我遗漏的吗?

【问题讨论】:

【参考方案1】:

您可以使用#set 将属性值设置为nil。见https://docs.mongodb.com/mongoid/master/tutorials/mongoid-persistence/#atomic。

irb(main):024:0> u.set(foo: nil)
D, [2020-10-05T21:31:20.167950 #18418] DEBUG -- : MONGODB | localhost:14400 req:15 conn:1:1 sconn:1088 | mongoid.update | STARTED | "update"=>"users", "ordered"=>true, "updates"=>["q"=>"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6'), "u"=>"$set"=>"foo"=>nil], "$db"=>"mongoid", "lsid"=>"id"=><BSON::Binary:0x7620 type=uuid data=0x606db89de7a04adf...>
D, [2020-10-05T21:31:20.169268 #18418] DEBUG -- : MONGODB | localhost:14400 req:15 | mongoid.update | SUCCEEDED | 0.001s
=> #<User _id: 5f7bc8642c97a647f27735c6, created_at: 2020-10-06 01:29:08.638566093 UTC, updated_at: 2020-10-06 01:29:20.656350934 UTC, bar: nil, bar1: 1, foo: nil>

然后#attributes 按预期工作:

irb(main):023:0> User.find(u.id).attributes
D, [2020-10-05T21:30:18.758322 #18418] DEBUG -- : MONGODB | localhost:14400 req:14 conn:1:1 sconn:1088 | mongoid.find | STARTED | "find"=>"users", "filter"=>"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6'), "$and"=>["_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6')], "$db"=>"mongoid", "lsid"=>"id"=><BSON::Binary:0x7620 type=uuid data=0x606db89de7a04adf...>
D, [2020-10-05T21:30:18.759791 #18418] DEBUG -- : MONGODB | localhost:14400 req:14 | mongoid.find | SUCCEEDED | 0.001s
=> "_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6'), "updated_at"=>2020-10-06 01:29:20.656 UTC, "created_at"=>2020-10-06 01:29:08.638 UTC, "bar1"=>1, "foo"=>nil

如果您认为 write_attribute 应该保留具有 nil 值的属性,您可以在 https://jira.mongodb.org/browse/MONGOID 创建一个工单来描述您的用例。

【讨论】:

【参考方案2】:

Mongo::Attributes::Dynamic 的文档中提到了这一点:

如果文档中不存在该属性,Mongoid 将不会为您提供 getter 和 setter,并将强制执行正常的 method_missing 行为。在这种情况下,您必须使用其他提供的访问器方法:([] 和 []=) 或 (read_attribute 和 write_attribute)。

所以你可以使用user[:bar]user.read_attribute(:bar)

【讨论】:

我知道这一点,但在我的示例中,我使用 write_attribute 设置一个新属性,我希望它在保存后可以访问,但当我将属性设置为无。 我不太了解 Mongo,你确定它的行为就像一个具有 nil 值的键存在吗?当您直接在 Mongo 中查找时会发生什么?这与查找 wss 根本没有设置的键时的行为相比如何?

以上是关于添加具有 nil 值的新动态属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 ifelse 添加具有条件值的新列

如何使用scala数据框添加具有以下行值的新列[重复]

在配置单元中添加具有恒定值的新列

从字典中添加具有映射值的新熊猫列[重复]

如何将具有值的新列添加到现有数据表?

在Angularjs中添加具有不同值的新HTML内容