Mongoengine: Update of field called size

Created on 8 Mar 2013  Â·  22Comments  Â·  Source: MongoEngine/mongoengine

When I do

cls.update('set_size' = 10)

I get

File "/usr/lib/python2.7/site-packages/mongoengine/document.py", line 327, in update
    return self.__class__.objects(**self._object_key).update_one(**kwargs)
File "/usr/lib/python2.7/site-packages/mongoengine/queryset.py", line 1563, in update_one
    update = QuerySet._transform_update(self._document, **update)
File "/usr/lib/python2.7/site-packages/mongoengine/queryset.py", line 1465, in _transform_update        
    field = cleaned_fields[-1]

It looks like the problem occurs when the field name is also match operator name (queryset.py:1416). I don't know your code so I don't dare to send patch but I think it can be solved by checking of length of _parts_ variable.

Most helpful comment

We really need this! A list of names we can't use will be a good temp fix.

All 22 comments

Hi you need to use a double underscore:

cls.update('set__size' = 10)

Oh sorry, it is typo in bug report. I am using double underscore and it does not work anyway.

Ah ok - what is cls? An object instance? Can you do provide a bigger test case as it should be well covered by the current test suite.

maybe the quotes ?

Sorry for delay, I somehow forgot about it.
The problem is "size" is comparison operator but i used is as a field name. It is evaluated as comparison in transform.py:175 and then there is no field name.

It does not work for any Document or queryset update().

Is there any way how to escape the "size" so it will be parsed as field instead as comparison operator?

Still a problem with mongoengine 0.8.7.

is it possible to use __raw__ in update ?

It's really needed to escape operators in queryset.

If it's not possible immediately, is it possible to add constrain to prevent same field name as operators?

Having now been bitten twice (can't use 'id' and can't update 'size'), can we at least have a list of things we can't use until this is fixed? Right now I find out what doesn't work when a new field name shows up and mongoengine crashes...

We really need this! A list of names we can't use will be a good temp fix.

Still a problem with mongoengine 0.15.3.

@Yevgnen Can you provide a failing code for me? So, I can work on this.

@erdenezul

Hello,

This happened when a field name is in COMPARISON_OPERATORS = ('ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', 'all', 'size', 'exists', 'not', 'elemMatch', 'type') in transform.py. Personally I think type is quite a common field name...

# -*- coding: utf-8 -*-

from mongoengine import StringField, connect, Document


class Demo(Document):

    field1 = StringField()
    field2 = StringField()
    type = StringField() 


connect(host='127.0.0.1', port=27017, db='demo')

Demo.objects(field1='field1').upsert_one(field2='field2', type='some value')

Thanks for the additional information @Yevgnen !

type is also python keyword

Any update here? Pretty hacky workaround provided here using __setattr__:

class Customer(Document):
    name = StringField(required=True)
    type = StringField(default="")

if __name__ == '__main__':
    c = Customer()
    c.name = "Joe"
    c.save()
    body = {'type': 'test4'}
    n = Customer.objects(name="Joe").first()
    for key in body.keys():
        n.__setattr__(key, body[key])
    n.save()
    c = Customer.objects(name="Joe").first()
    print c.type

But it's a decent amount of boilerplate for something that really ought to be built in.

Unfortunately, no updates.
On Fri, Feb 1, 2019 at 10:33 Nick Faughey notifications@github.com wrote:

Any update here? Pretty hacky workaround provided here
https://github.com/MongoEngine/django-mongoengine/issues/39 using
__setattr__:

class Customer(Document):
name = StringField(required=True)
type = StringField(default="")
if __name__ == '__main__':
c = Customer()
c.name = "Joe"
c.save()
body = {'type': 'test4'}
n = Customer.objects(name="Joe").first()
for key in body.keys():
n.__setattr__(key, body[key])
n.save()
c = Customer.objects(name="Joe").first()
print c.type

But it's a decent amount of boilerplate for something that really ought to
be built in.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MongoEngine/mongoengine/issues/244#issuecomment-459583680,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AP-U3l6CiyIrdgkuC2r23CB4YDmzIiLVks5vI6eBgaJpZM4AfA0y
.

I faced the same issue described by @Yevgnen using the 0.17.0 version of mongoengine.
I believe that it's crucial to underline this issue in some way in the documentation or to properly clarify the raised error.

‘type’ is just a built in function, not keyword. @erdenezul

We just got bitten by this now. Broken code:

document.update(foo='bar', type='boz')

our workaround:

document.type = 'boz'
document.save()
document.update(foo='bar')

I think this was fixed on v0.10.7

  • Fixed support for __ to escape field names that match operators names in update

There is a closed issue #1176 and a merged PR #1351

I ran the same code as @Yevgnen adding the __ escape suffix, and it worked for me.

# -*- coding: utf-8 -*-

from mongoengine import StringField, connect, Document


class Demo(Document):

    field1 = StringField()
    field2 = StringField()
    type = StringField() 


connect(host='127.0.0.1', port=27017, db='demo')

Demo.objects(field1='field1').upsert_one(field2='field2', type__='some value')

I checked the db using the mongo shell, and the field name is type without the __ suffix

> db.demo.find()
{ "_id" : ObjectId("5ef0f2a61c85025c2b724054"), "field1" : "field1", "field2" : "field2", "type" : "some value" }

Tested with Python 3.8.2 on Ubuntu 20.04, MongoDB 4.0, mongoengine 0.20.0, pymongo 3.10.1

Just got the error while trying to update a field called size.

File "./service/db_service.py", line 90, in service_update_estate
    house.update(size=size,
  File "/usr/local/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/mongoengine/document.py", line 610, in update
    return self._qs.filter(**self._object_key).update_one(**kwargs)
  File "/usr/local/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/mongoengine/queryset/base.py", line 631, in update_one
    return self.update(
  File "/usr/local/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/mongoengine/queryset/base.py", line 555, in update
    update = transform.update(queryset._document, **update)
  File "/usr/local/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/mongoengine/queryset/transform.py", line 301, in update
    field = cleaned_fields[-1]
IndexError: list index out of range 

Not fixed

Python 3.9.0, macOS11.1, MongoDB v4.2.7 et mongoengine 0.23.0

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ajdas-code picture ajdas-code  Â·  4Comments

ibrahimyilmaz picture ibrahimyilmaz  Â·  5Comments

aakashef picture aakashef  Â·  3Comments

nilay-gpt picture nilay-gpt  Â·  4Comments

ZEROF picture ZEROF  Â·  4Comments