MongoDB的“E11000重复键错误索引”创建节约mongoengine ReferenceField(DBREF)

问题描述:

我试图在我的测试运行从JSON文件加载测试夹具时(以匹配在Django使用夹具装载风格相似)。这是我到目前为止的代码;MongoDB的“E11000重复键错误索引”创建节约mongoengine ReferenceField(DBREF)

from django.utils import simplejson as json 
from mongoengine import base as mongobase 
from mongoengine import connect 
from pymongo import json_util 

db = connect("DATABASENAME") 

# Clear out the current collections. 
for collection in db.collection_names(): 
    if collection == 'system.indexes': 
     continue 
    db.drop_collection(collection) 


# Open json fixtures 

f = open('path/to/test_fixtures.json', 'r') 
datas = json.loads(f.read(), object_hook=json_util.object_hook) 

# For each serialised model instance, loop through and save to the database. 

for data in datas: 

    print data 

    if data['_cls'] not in mongobase._document_registry: 
     print "Skipping %s" % data['_cls2'] 
     continue 

    model = mongobase._document_registry[data['_cls']] 
    model_instance = model._from_son(data) 
    model_instance.save(force_insert=True) 

这似乎工作,但是,当其中一个模型有一个ReferenceField,它失败。抱怨重复的关键。你会发现有一个print语句在那里显示的字典内容,在一个例子来看,我会得到下面的输出,所有的错误之前看起来很好

{u'_types': [u'Account'], u'status': u'ok', u'name': u'Alice', u'local_id': u'3', u'_cls': u'Account', u'members': [], u'_id': ObjectId('4f17f0855585d32457000001'), u'email': u'[email protected]', u'permissions': []} 
{u'_types': [u'Account'], u'status': u'ok', u'name': u'Bob', u'local_id': u'2', u'_cls': u'Account', u'members': [], u'_id': ObjectId('4f17f0855585d32457000000'), u'email': u'[email protected]', u'permissions': []} 
{u'_types': [u'Account'], u'status': u'ok', u'name': u'company', u'_cls': u'Account', u'members': [], u'_id': ObjectId('4f17f0855585d32457000002'), u'email': u'[email protected]', u'permissions': []} 
{u'_types': [u'Membership'], u'parent_account': DBRef(u'account', ObjectId('4f17f0855585d32457000002')), u'member': DBRef(u'account', ObjectId('4f17f0855585d32457000001')), u'role': u'member', u'_cls': u'Membership', u'_id': ObjectId('4f17f0855585d32457000003')} 

最后,错误的是:

Traceback (most recent call last): 
    File "/home/vagrant/.virtualenvs/engineclub/lib/python2.6/site-packages/django/test/testcases.py", line 292, in __call__ 
    self._pre_setup() 
    File "/home/vagrant/.virtualenvs/engineclub/lib/python2.6/site-packages/django/test/testcases.py", line 259, in _pre_setup 
    self._fixture_setup() 
    File "/vagrant/engineclub/engineclub/apps/notifications/tests.py", line 67, in _fixture_setup 
    model_instance.save(force_insert=True) 
    File "/home/vagrant/.virtualenvs/engineclub/lib/python2.6/site-packages/mongoengine/document.py", line 177, in save 
    _refs=_refs) 
    File "/home/vagrant/.virtualenvs/engineclub/lib/python2.6/site-packages/mongoengine/document.py", line 183, in save 
    raise OperationError(message % unicode(err)) 
OperationError: Tried to save duplicate unique keys (E11000 duplicate key error index: test_aliss.account.$_id_ dup key: { : ObjectId('4f17f0855585d32457000001') }) 

它插入其中有只账户集合的引用一个会员实例时,似乎抱怨是考虑重复键。$ ID

让我知道,如果有任何其他的信息,我可以包括,我会加入但JSON文件,它非常像印刷类型的字典(也是唯一拥有3个账户,然后一个成员)。有一件事我注意到,当我从保存中删除force_insert时,它似乎根本没有保存任何东西(因此似乎传递正常)。

+0

我想你所提供的对象ID的手动,并因此创造了DBREF用硬编码IDS对象。 也正确保存帐户?我想知道是否有一些解引用问题正在发生,并且当您保存成员资格时,会尝试重新保存Account对象。 – Ross

+0

是的,对象ID是手动提供的。我怀疑问题可能与此有关,mongoengine似乎并没有帮助序列化。该帐户被保存,我加入了环快速行做到了这一点:''打印数据,Account.objects.count(),Membership.objects.count()''和计数是为帐户(增加会员因为第一次失败,所以停留在0) – d0ugal

+0

处理pymongo direct并将数据保存在正确的集合中可能会更容易。为我提供一个测试案例,我会研究它 - 在github上添加一张票 – Ross

尝试使用Mixer

from mixer.backend.mongoengine import mixer 

mixer.blend(MyDocument)