MongoEngine / MongoEngine/mongoengine

Can not upsert when has field named 'id'

Open
#1,940 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4.3k
Forks
1.2k
Avg merge
4h 41m
Merged PRs (30d)
11

Description

When upserting a document, if there's a field named id, error happened.

~/test.py in <module>
     11 connect(db='test1', host='127.0.0.1', port=27017)
     12 
---> 13 A.objects(x=1).upsert_one(id=1)

/usr/local/var/pyenv/versions/3.6.6/envs/one/lib/python3.6/site-packages/mongoengine/queryset/base.py in upsert_one(self, write_concern, **update)
    562 
    563         if atomic_update.raw_result['updatedExisting']:
--> 564             document = self.get()
    565         else:
    566             document = self._document.objects.with_id(atomic_update.upserted_id)

/usr/local/var/pyenv/versions/3.6.6/envs/one/lib/python3.6/site-packages/mongoengine/queryset/base.py in get(self, *q_objs, **query)
    270 
    271         try:
--> 272             result = next(queryset)
    273         except StopIteration:
    274             msg = ('%s matching query does not exist.'

/usr/local/var/pyenv/versions/3.6.6/envs/one/lib/python3.6/site-packages/mongoengine/queryset/base.py in __next__(self)
   1491         doc = self._document._from_son(
   1492             raw_doc, _auto_dereference=self._auto_dereference,
-> 1493             only_fields=self.only_fields)
   1494 
   1495         if self._scalar:

/usr/local/var/pyenv/versions/3.6.6/envs/one/lib/python3.6/site-packages/mongoengine/base/document.py in _from_son(cls, son, _auto_dereference, only_fields, created)
    720             data = {k: v for k, v in data.items() if k in cls._fields}
    721 
--> 722         obj = cls(__auto_convert=False, _created=created, __only_fields=only_fields, **data)
    723         obj._changed_fields = changed_fields
    724         if not _auto_dereference:

/usr/local/var/pyenv/versions/3.6.6/envs/one/lib/python3.6/site-packages/mongoengine/base/document.py in __init__(self, *args, **values)
     76                     'The fields "{0}" do not exist on the document "{1}"'
     77                 ).format(_undefined_fields, self._class_name)
---> 78                 raise FieldDoesNotExist(msg)
     79 
     80         if self.STRICT and not self._dynamic:

FieldDoesNotExist: The fields "{'_id'}" do not exist on the document "A"

I guess a field named id should be fine since I see example like

user = User.objects.get(id=user_id)
user.switch_db('archive-db')
user.save()

in the document.

from mongoengine import IntField, Document, connect


class A(Document):
    x = IntField()
    id = IntField()


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

A.objects(x=1).upsert_one(id=1)  # <A: A object>
A.objects(x=1).upsert_one(id=1)  # Error

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the two calls in test.py and start by reading mongoengine/queryset/base.py around upsert_one, then follow the document construction path in mongoengine/base/document.py. Confirm that a document with an id field can be upserted repeatedly without FieldDoesNotExist for _id, and add or run regression coverage for both calls.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.