MongoDB «E11000 индекс ошибки повторяющегося ключа» при создании сохранения ReferenceField mongoengine (DBRef)

Я пытаюсь загрузить тестовые фикстуры из файла json в своих тестовых прогонах (чтобы соответствовать аналогичному стилю загрузки фикстур, используемому в Django). Это код, который у меня есть до сих пор;

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, происходит сбой. Жалоба на дубликат ключа. Вы заметите, что там есть оператор печати, чтобы показать содержимое dict, в примере запуска я получу следующий вывод, который все выглядит нормально до ошибки

{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') })

Кажется, он жалуется на дублирующийся ключ в account.$id при вставке экземпляра membership, который имеет ссылку только на коллекцию аккаунтов.

Дайте мне знать, если есть какая-либо другая информация, которую я могу включить, я бы добавил файл JSON, однако он очень похож на печатные диктовки (и имеет только 3 учетных записи, за которыми следует одно членство). Я заметил одну вещь: когда я удаляю force_insert из сохранения, кажется, что он вообще ничего не сохраняет (и, таким образом, кажется, что он проходит нормально).


person d0ugal    schedule 20.01.2012    source источник
comment
Я так понимаю, вы предоставляете идентификатор объекта вручную и, следовательно, создаете объекты DBRef с жестко закодированными идентификаторами. Также правильно ли сохраняются учетные записи? Мне интересно, возникает ли какая-то проблема с разыменованием, и когда вы сохраняете членство, он пытается повторно сохранить объект учетной записи.   -  person Ross    schedule 20.01.2012
comment
Да, идентификаторы объектов предоставляются вручную. Я подозреваю, что проблема может быть связана с этим, mongoengine, похоже, не помогает с сериализацией. Учетные записи сохраняются, я добавил быструю строку в цикле, который делал это: print data, Account.objects.count(), Membership.objects.count() и количество учетных записей увеличивалось (членство застряло на 0, так как первая не удалась)   -  person d0ugal    schedule 20.01.2012
comment
Может быть проще иметь дело с pymongo direct и сохранять данные в правильных коллекциях. Предоставьте мне тестовый пример, и я его изучу - добавьте тикет на github   -  person Ross    schedule 20.01.2012
comment
как вы создаете файлы приборов?   -  person josephmisiti    schedule 22.01.2012
comment
@JosephMisiti с помощью метода, описанного здесь: groups.google.com/ форум/?fromgroups#!topic/mongoengine-users/   -  person d0ugal    schedule 02.02.2012


Ответы (1)


Попробуйте использовать Mixer:

from mixer.backend.mongoengine import mixer

mixer.blend(MyDocument)
person klen    schedule 07.01.2014