Как я могу создать документ MongoEngine со ссылочными документами, которые уже находятся в базе данных?

У меня уже есть класс документов, хранящийся в моей базе данных (Flask-MongoEngine), и у меня уже есть их уникальный идентификатор. Мой реальный пример более сложен, но, скажем, он выглядит так:

class Stuff(Document):
    stuffstuff = StringField()

Я хотел бы создать коллекцию экземпляров Stuff из Stuffs, которые уже есть в моей базе данных. Скажем, я хочу создать новый экземпляр класса ниже из экземпляров Stuff, которые в настоящее время находятся в моей базе данных.

class StuffsCollection(Document):
    lotsofstuffs = ListField(ReferenceField(Stuff))

В документации ReferenceField это выглядит как единственный способ создать экземпляр StuffsCollection должен сначала создать экземпляры Stuff, а затем передать их в качестве аргументов ключевого слова. Например:

a_thing = Stuff(stuffstuff="here's a thing")
a_thing.save()
some_things = StuffsCollection(lotsofstuffs=[a_thing])
some_things.save()

Поскольку у меня уже есть уникальные идентификаторы, которые ссылаются на мои экземпляры Stuff, могу ли я просто сказать MongoEngine использовать эти существующие Stuffs в качестве аргументов ключевого слова в новой коллекции StuffsCollection? Похоже, это будет более эффективно, чем запрос к базе данных для каждого документа, затем создание нового экземпляра этого документа, а затем передача каждого в мой новый ListField.


person teechap    schedule 26.12.2013    source источник


Ответы (1)


Вам необходимо передать DBRef объектов:

from bson import DBRef, ObjectId

a_id = ObjectId('somevalidid')
a_ref = DBRef('stuff', a_id)

some_things = StuffsCollection(lotsofstuffs=[a_ref])
some_things.save()

MongoEngine сохраняет ReferenceField с использованием DBRef или ObjectID. Аргумент 'stuff' для DBRef будет просто проигнорирован, если поле настроено с dbref=False. В противном случае это должно быть имя коллекции для Stuff объектов.

Однако вам необходимо передать DBRef объектов в конструктор в обоих случаях из-за способа реализации проверки в ReferenceField.

person Nicolas Cortot    schedule 26.12.2013
comment
Спасибо большое! Еще одна вещь: как передать существующие документы (для которых я уже знаю идентификатор и которые наследуются от базового документа, такого как класс Stuff выше) в новую коллекцию StuffsCollection как встроенные документы, а не ссылочные документы ? - person teechap; 27.12.2013
comment
Со встроенными документами вам необходимо передать весь документ со всеми его данными в новый контейнер, поэтому нет никакого способа сначала получить его из БД. - person Nicolas Cortot; 27.12.2013