Mongoid不会通过.create覆盖现有文档

时间:2013-09-20 14:52:58

标签: ruby mongodb transactions mongoid

我有以下课程:

class Magazine
  include Mongoid::Document

  field :name
  field :count
  field :_id, default: -> { name }

我通过Magazine.create!(name: "Yolo", count: 2)创建此类型的新文档。这很好用。现在,当我想在MongoDB中更新这个文档时,由于计数已经改变,我认为这样可行:

Magazine.create!(name: "Yolo", count: 42)

名称映射到相同的标识符,因此文档会被覆盖。虽然操作似乎成功,但在MongoDB中,文档没有更新。

相反,我必须这样做:

Magazine.where(name: "Yolo").first.update_attributes!(count: 42)

哪个有效,但有人可以解释为什么我的第一种方法不起作用,以及我的第二种方法是通过Mongoid更新文档的常用方法吗?

2 个答案:

答案 0 :(得分:2)

问题在我的机器上重现,我找到了解决方案。

根据{{​​3}}或document,如果发生验证错误

Model#create!会引发错误,而不是数据库错误 。所以这不是你问题的解决方案。

the code on github with(safe: true)可以告诉Mongoid引发Runtime Persistence Option中定义的数据库错误。在你的情况下。错误如下:

1.9.3-p0 :009 > Magazine.with(safe: true).create!(name: "Yolo", count: 42)
Moped::Errors::OperationFailure: The operation: #<Moped::Protocol::Command
  @length=71
  @request_id=7
  @response_to=0
  @op_code=2004
  @flags=[]
  @full_collection_name="mongoid.$cmd"
  @skip=0
  @limit=-1
  @selector={:getlasterror=>1, :safe=>true}
  @fields=nil>
failed with error 11000: "E11000 duplicate key error index: mongoid.magazines.$_id_  dup key: { : \"Yolo\" }"

此外,安全模式可以在配置YAML中设置为默认值,如the driver Moped中所述。

也许您希望找到一个Magazine.find("Yolo")的杂志来默认使用MongoDB创建的_id索引。即使_idname相同,但Mongoid也不够聪明,无法使用_id来查找文档。

答案 1 :(得分:1)

我想我有点惊讶你的第二次创造!不会引发错误。

尝试使用与update相结合的find方法,这是用于更新属性的非常常见的单行程序:

Magazine.find('Yolo').update_attributes(count: 42)