Использование MongoEngine для замены значения в ListField - PullRequest
0 голосов
/ 12 июня 2019

Я создаю скрипт, использующий MongoEngine для обновления коллекции. Обновление должно изменить определенное поле в ListField.
Используя raw pyMongo, обновление будет выглядеть так:

db.books.update({"authors": {"$elemMatch": {"$eq": "matt"}}}, {'$set': {"authors.$": "Mathew"}}).

К сожалению, я должен сделать это в MongoEngine (так как остальная система работает с ним, и мне это нужно для согласованности), и поскольку это может быть очень большая коллекция, я предпочитаю, чтобы mongo обрабатывал обновление, а не загружал всю коллекцию и обновить каждый элемент книги в моем коде Python.

Я пытался сделать тот же запрос с Mongo Engine:

class Book(DynamicDocument):
    meta = {'collection': 'books', 'strict': False}

    authors = ListField()

    @classmethod
    def update_author_name(cls, oldVal, newVal):
        filter = Q(**{"authors__in": [oldVal]})
        cls.objects(filter).update(**{authors+".$": newVal})

однако я получаю исключение:

{InvalidQueryError}field names cannot contain dots (".") or null characters ("\0"), and they must not start with a dollar sign ("$").

1 Ответ

1 голос
/ 12 июня 2019

mongoengine не имеет поддержки для этого, лучшее, что вы могли бы достичь, это использовать raw и приблизиться к синтаксису pymongo, как это:

Book.objects(__raw__={"authors": {"$elemMatch": {"$eq": "Math"}}}).update(__raw__={'$set': {"authors.$": "Mathew"}})

Но добавленная стоимость невелика по сравнению с получением фактической коллекции и выполнением запроса через pymongo

c = Book._get_collection()
c.update({"authors": {"$elemMatch": {"$eq": "matt"}}}, {'$set': {"authors.$": "Mathew"}})
...