Mongoid 1-N插入重复键错误
Mongoid 1-N insert duplicate key error
我从 Mongoid 4.0.0 和 Rails 4 得到了一个奇怪的行为,我有一个 1-N 关系,当我试图保存关系。让我给你看一些代码:
module MyEngine
class Collection
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :price, type: Integer, default: 0
has_many :purchases, class_name: 'MyEngine::Purchase'
validates_presence_of :name
end
end
module MyEngine
class Purchase
include Mongoid::Document
include Mongoid::Timestamps
field :paid, type: Integer, default: 0
belongs_to :collection, class_name: 'MyEngine::Collection'
end
end
这是失败的测试:
test "should save purchase" do
col = Collection.create(name:'test')
pur = Purchase.new
pur.collection_id = col.id
assert pur.save, "Could not save purchase"
end
执行此测试会产生以下结果:
Moped::Errors::OperationFailure: The operation: #<Moped::Protocol::Command
@length=74
@request_id=7
@response_to=0
@op_code=2004
@flags=[]
@full_collection_name="dummy_test.$cmd"
@skip=0
@limit=-1
@selector={:getlasterror=>1, :w=>1}
@fields=nil>
failed with error 11000: "insertDocument :: caused by :: 11000 E11000 duplicate key error index: dummy_test.loot_collections.$_id_ dup key: { : ObjectId('54c3057350686f51a8000000') }"
我在创建 collection 之后添加了一个 puts
命令来验证它的 ID 确实与被复制的相同。此外,删除语句 pur.collection_id = col.id
会导致以下错误:NoMethodError: undefined method 'insert' for nil:NilClass
这让我相信当我尝试保存 Purchase object 时,Mongoid 会自动尝试插入1-N关系,虽然已经持久化了
请注意,将 pur.collection_id = col.id
更改为 pur.collection = col
不会有任何变化。
我可以通过将 Collection.create
更改为 Collection.new
来解决此问题,但这不是一个可行的解决方案,如您所想,我需要能够创建已存在的购买 Collections.
为什么会这样?我查看了 documentation 并没有提到这种行为,在我看来这是没有意义的(或者我可能已经看这个屏幕太久了)。
知道如何解决这个问题吗?
所以我终于弄明白了,将模型 Collection
重命名为其他名称解决了问题,似乎 Mongoid 不喜欢模型的名称,即使在隔离的命名空间引擎中也是如此。
我从 Mongoid 4.0.0 和 Rails 4 得到了一个奇怪的行为,我有一个 1-N 关系,当我试图保存关系。让我给你看一些代码:
module MyEngine
class Collection
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :price, type: Integer, default: 0
has_many :purchases, class_name: 'MyEngine::Purchase'
validates_presence_of :name
end
end
module MyEngine
class Purchase
include Mongoid::Document
include Mongoid::Timestamps
field :paid, type: Integer, default: 0
belongs_to :collection, class_name: 'MyEngine::Collection'
end
end
这是失败的测试:
test "should save purchase" do
col = Collection.create(name:'test')
pur = Purchase.new
pur.collection_id = col.id
assert pur.save, "Could not save purchase"
end
执行此测试会产生以下结果:
Moped::Errors::OperationFailure: The operation: #<Moped::Protocol::Command
@length=74
@request_id=7
@response_to=0
@op_code=2004
@flags=[]
@full_collection_name="dummy_test.$cmd"
@skip=0
@limit=-1
@selector={:getlasterror=>1, :w=>1}
@fields=nil>
failed with error 11000: "insertDocument :: caused by :: 11000 E11000 duplicate key error index: dummy_test.loot_collections.$_id_ dup key: { : ObjectId('54c3057350686f51a8000000') }"
我在创建 collection 之后添加了一个 puts
命令来验证它的 ID 确实与被复制的相同。此外,删除语句 pur.collection_id = col.id
会导致以下错误:NoMethodError: undefined method 'insert' for nil:NilClass
这让我相信当我尝试保存 Purchase object 时,Mongoid 会自动尝试插入1-N关系,虽然已经持久化了
请注意,将 pur.collection_id = col.id
更改为 pur.collection = col
不会有任何变化。
我可以通过将 Collection.create
更改为 Collection.new
来解决此问题,但这不是一个可行的解决方案,如您所想,我需要能够创建已存在的购买 Collections.
为什么会这样?我查看了 documentation 并没有提到这种行为,在我看来这是没有意义的(或者我可能已经看这个屏幕太久了)。
知道如何解决这个问题吗?
所以我终于弄明白了,将模型 Collection
重命名为其他名称解决了问题,似乎 Mongoid 不喜欢模型的名称,即使在隔离的命名空间引擎中也是如此。