Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Insertion failure when replacing unknown field with dbref value #1255

Closed
smeng9 opened this Issue Apr 4, 2019 · 1 comment

Comments

Projects
None yet
2 participants
@smeng9
Copy link
Contributor

smeng9 commented Apr 4, 2019

Background

When javascript processes JSON or when MongoDB handles DBRef they keep the key value pairs ordered.
As we can see from the MongoDB source code, the expected format for DBRef should always have $ref in the first place, $id in the middle place, and $db in the last place as {$ref:, $id:, $db:}
https://github.com/mongodb/mongo/blob/b21647a5e19e5980186e57f77be0b1e0ef92a087/src/mongo/db/update/storage_validation.cpp#L86

Expected Behavior

Tell us what should happen.

Below are the steps to reproduce the issue

  1. define a works'' resource with allow_unknown'' set to True, and ``schema'' set to {}
  2. create an item with {"title": "my work", "owner": {"$ref": "people", "$id": "objectid_in_people"}}
    curl 'http://127.0.0.1:5000/works/ -X POST-H 'content-type: application/json' -d '{"title": "my work", "owner": {"$ref": "people", "$id": "objectid_in_people"}}'
  3. get the created item using curl http://127.0.0.1:5000/works/objectid_in_work and we will get
    {"title": "my work", "owner": {"$id": "objectid_in_people", "$ref": "people"}}
  4. Try to PUT the data from step 3 to the same item endpoint

We noticed the order of $id and $ref are swapped in the GET response.
If we swap the order of $id and $ref in owner field again to {"$ref": "people", "$id": "objectid_in_people"}, then we are able to successfully replace the document.

When we are returning a dictionary for the DBRef, we are not using the OrderedDict, and we lose the order.

if isinstance(obj, DBRef):

Actual Behavior

Tell us what happens instead.

Traceback (most recent call last): 
File "/usr/local/lib/python3.7/site-packages/eve/io/mongo/mongo.py", line 509, in change_request
    coll.replace_one(filter, changes) if replace else coll.update_one( 
File "/usr/local/lib/python3.7/site-packages/pymongo/collection.py", line 925, in replace_one collation=collation, session=session), 
File "/usr/local/lib/python3.7/site-packages/pymongo/collection.py", line 851, in _update_retryable _update, session) 
File "/usr/local/lib/python3.7/site-packages/pymongo/mongo_client.py", line 1248, in _retryable_write return self._retry_with_session(retryable, func, s, None) 
File "/usr/local/lib/python3.7/site-packages/pymongo/mongo_client.py", line 1201, in _retry_with_session return func(session, sock_info, retryable) 
File "/usr/local/lib/python3.7/site-packages/pymongo/collection.py", line 847, in _update retryable_write=retryable_write) 
File "/usr/local/lib/python3.7/site-packages/pymongo/collection.py", line 818, in _update _check_write_command_response(result) 
File "/usr/local/lib/python3.7/site-packages/pymongo/helpers.py", line 217, in _check_write_command_response _raise_last_write_error(write_errors) 
File "/usr/local/lib/python3.7/site-packages/pymongo/helpers.py", line 199, in _raise_last_write_error raise WriteError(error.get("errmsg"), error.get("code"), error) 
pymongo.errors.WriteError: Found $id field without a $ref before it, which is invalid.

Environment

  • Python version: 3.7.3
  • Eve version: 0.8.1

Suggested Fix

We can switch to OrderedDict to preserve the order. When user post DBRef data structures in JSON, they should also be aware of the order of the key value pairs.

@nicolaiarocci nicolaiarocci added this to the 0.8.2 milestone Apr 4, 2019

@nicolaiarocci

This comment has been minimized.

Copy link
Member

nicolaiarocci commented Apr 4, 2019

Sure, go ahead with the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.