2013-04-24 2 views
0

У меня есть следующий Mongoengine документ:Как Mongoengine решает, являются ли 2 EmbeddedDocuments равными или нет?

class MyEmbed(EmbeddedDocument): 
    embedField = StringField(primary_key=True) 
    varField = StringField() 

class TestDoc(Document): 
    myField = StringField() 
    embed_list = ListField(EmbeddedDocumentField(MyEmbed)) 

Так я держу список вложенных документов, к которым я желаю, чтобы добавить новые документы, если они не существуют уже. Проблема в том, что когда я использую оператор атомарного обновления add_to_set, все не получается так, как я их хочу. Это то, что я пытаюсь сделать:

embed1 = models.MyEmbed(embedField="F1") 
parent = models.TestDoc(myField="ParentField") 
embed_list = [] 
embed_list.append(embed1) 
parent.embed_list = embed_list 
parent.save() 

embed2 = models.MyEmbed(embedField="F1", varField="varField") 
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2) 

Проблема заключается в том, что после того, как делать это, я имею в БД список вложенных документов с 2-х элементов. И то, что я хочу, - это решить одно поле (embedField в этом случае), равны ли 2 EmbeddedDocuments или нет, а не учитывать все свойства. Мои вопросы:

  • Каковы критерии по умолчанию, согласно которым Mongoengine решает, равны ли 2 EmbeddedDocuments или нет?
  • Как я могу переопределить функцию, которая делает Mongoengine решающим, когда 2 EmbeddedDocuments равны или нет?

Спасибо!

ответ

2

Фактическая проверка выполняется внутри MongoDB и не mongoengine.

Объект, отправленный в mongodb, должен быть таким же, но это то, где он становится хитрым, поскольку порядок BSON важен, а в python со словарями нет. Когда конвертация для отправки в mongodb mongoengine просто передает словарь. Это ошибка - так что я добавил #296 и исправлю за 0,8

+0

я вижу. Спасибо за объяснение. Тогда я действительно жду 0.8 ...: D – Clara

-1

См https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/document.py#L51 и https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/base/document.py#L52:

def __eq__(self, other): 
    if isinstance(other, self.__class__): 
     return self._data == other._data 
    return False 

Это сравнение dicts из встроенных данных документов. Таким образом, вы можете переопределить этот метод.

Если вы посмотрите на обновление документа, который вызывает обновление QuerySet (найти add_to_set и addToSet), вы можете обнаружить, что проверка mongoengine doesnt't существует документ в списке и просто вызовите mongo $addToSet operation: https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/queryset/transform.py#L156.

В вашем коде у вас есть документ MyEmbed(embedField="F1") и попробуйте добавить другой документ MyEmbed(embedField="F1", varField="varField") так логично: он добавляет новый документ. Если вы попробуете следующий код:

embed1 = models.MyEmbed(embedField="F1") 
parent = models.TestDoc(myField="ParentField") 
embed_list = [] 
embed_list.append(embed1) 
parent.embed_list = embed_list 
parent.save() 

embed2 = models.MyEmbed(embedField="F1", varField="varField") 
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2) 

embed3 = models.MyEmbed(embedField="F1") 
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed3) 

embed4 = models.MyEmbed(embedField="F1", varField="varField") 
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed4) 

вы можете обнаружить, что родитель содержит только embed1 и embed2.

Итак, для решения проблемы вы можете переопределить метод __eq__ и проверить документ в списке, но вы должны найти другое решение для списка документов обновления, поскольку оно имеет прямой вызов метода mongo.

+0

Его правда использует __eq__ для локальных сравнений, но не для запроса, как показано в том виде, как это делается внутри MongoDB. – Ross

Смежные вопросы