Skip to content

Error with atomic updates and modifier operator: InvalidQueryError("Updates must supply an operation eg: set__FIELD=value") #843

@mamigot

Description

@mamigot

(I am using mongoengine==0.8.7 and flask-mongoengine==0.7.1; though the error is traced to a mongoengine file independent of Flask, I am posting this in case it's a problem with their compatibility)

The mongoengine docs state that the following code is equivalent.

>>> BlogPost.objects(id=post.id).update(title='Example Post')
>>> BlogPost.objects(id=post.id).update(set__title='Example Post')

However, when the modifier isn't set as in the former example, I get the following error. Notice that it disappears when I provide the modifier, however:

>>> BlogPost.objects(slug='slug3').update(title='new_title')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/miguelamigot/.virtualenvs/pw-venv/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 430, in update
    update = transform.update(queryset._document, **update)
  File "/Users/miguelamigot/.virtualenvs/pw-venv/lib/python2.7/site-packages/mongoengine/queryset/transform.py", line 233, in update
    raise InvalidQueryError("Updates must supply an operation "
mongoengine.errors.InvalidQueryError: Updates must supply an operation eg: set__FIELD=value

>>> BlogPost.objects(slug='slug3').update(set__title='new_title')
1

By looking at the update(_doc_cls=None, **update) function in transform.py, it's clear that it expects "set__" to come before each key. Here it is:

def update(_doc_cls=None, **update):
    """Transform an update spec from Django-style format to Mongo format.
    """
    mongo_update = {}
    for key, value in update.items():
        if key == "__raw__":
            mongo_update.update(value)
            continue
        parts = key.split('__')
        # Check for an operator and transform to mongo-style if there is
        op = None
        if parts[0] in UPDATE_OPERATORS:
            op = parts.pop(0)
            # Convert Pythonic names to Mongo equivalents
            if op in ('push_all', 'pull_all'):
                op = op.replace('_all', 'All')
            elif op == 'dec':
                # Support decrement by flipping a positive value's sign
                # and using 'inc'
                op = 'inc'
                if value > 0:
                    value = -value
            elif op == 'add_to_set':
                op = 'addToSet'
            elif op == 'set_on_insert':
                op = "setOnInsert"

Later in the function (no value is assigned to op in the meantime)...

if not op:
            raise InvalidQueryError("Updates must supply an operation "
                                    "eg: set__FIELD=value")

Please let me know; thank you!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions