-
Notifications
You must be signed in to change notification settings - Fork 333
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
Implement $arrayToObject operator #624
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #624 +/- ##
===========================================
+ Coverage 94.76% 94.81% +0.05%
===========================================
Files 16 17 +1
Lines 3247 3281 +34
===========================================
+ Hits 3077 3111 +34
Misses 170 170
Continue to review full report at Codecov.
|
I'll add some tests for those missing lines for coverage |
It looks like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great works, thanks for adding.
tests/test__mongomock.py
Outdated
@@ -3065,6 +3065,36 @@ def test_aggregate_date_to_string(self): | |||
] | |||
self.cmp.compare.aggregate(pipeline) | |||
|
|||
def test_aggregate_array_to_object(self): | |||
self.cmp.do.drop() | |||
self.cmp.do.insert_one({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use insert_many to add all those docs at once.
tests/test__collection_api.py
Outdated
}] | ||
self.assertEqual(expect, list(actual)) | ||
|
||
with self.assertRaises(TypeError): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you could use a table test: create a list of items
that should trigger an error and then iterate over them and do an aggregation and an asserRaises for each of them.
tests/test__collection_api.py
Outdated
|
||
with self.assertRaises(TypeError): | ||
collection.aggregate([ | ||
{'$addFields': {'items': 100}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add all those errors in test__mongomock using compare_exceptions
mongomock/aggregate.py
Outdated
if parsed is None: | ||
return None | ||
|
||
if not isinstance(parsed, list): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general were list
is supported, tuple
is supported as well. Can you check on pymongo
and update it here please?
mongomock/aggregate.py
Outdated
raise TypeError('$arrayToObject only supports arrays') | ||
|
||
def check_doc(elements): | ||
return all([isinstance(x, dict) and 'k' in x and 'v' in x and len(x) == 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need the []
here; Also you might be able to check with set equality:
return all(isinstance(x, dict) and x.keys() == {'k', 'v'} for x in elements)
mongomock/aggregate.py
Outdated
for x in elements]) | ||
|
||
def check_arr(elements): | ||
return all([isinstance(x, list) and len(x) == 2 for x in elements]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here as well, please drop the []
and allow for tuple
mongomock/aggregate.py
Outdated
|
||
arr_to_obj = {} | ||
for elements in parsed: | ||
if isinstance(elements, list): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one can just be built with arr_to_obj = dict(parsed)
Thanks for the thorough review and your suggestions. I've implemented your requests and squashed my commits together. In addition to your requests I've made the following changes:
While checking PyMongo I've noticed that following exception messages can be thrown:
All of the messages can be seen in the mongo repo. My implementation doesn't check the reason for an OperationFailure in most cases and uses a generic error message. If you want I can change the code so that the same messages are used, but I wanted to check with you before adding more complexity to the code. EDIT: It looks like I broke something with Python 2.7. I'll take a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the neat changes..
- Totally OK not to have the same error message, as long as it's the same type. So let's keep it simpler.
- I prefer that we don't account for old versions of pymongo so your solution is best.
Please try to fix the python 2.7 version and my 2 little comments on indentation then I'll merge.
mongomock/aggregate.py
Outdated
return None | ||
|
||
if not isinstance(parsed, (list, tuple)): | ||
raise OperationFailure('$arrayToObject requires an array input, ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please break after OperationFailure(
: that helps with cleaner indentation that does not depend on the length of the class name.
mongomock/aggregate.py
Outdated
if all(isinstance(x, (list, tuple)) and len(x) == 2 for x in parsed): | ||
return dict(parsed) | ||
|
||
raise OperationFailure('arrays used with $arrayToObject must contain documents ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, break after OperationFailure(
Python 2.7 should be fixed now. |
Hi!
I've implemented the arrayToObject operator for the aggregation pipeline.
I've added tests for all the edge cases I could think of:
Duplicated keys are also accounted for and tested (latest found value is used, overwriting previous values), but there is a caveat in the mongo documentation for earlier versions. I'm not sure if this should be accounted for or mocking the behaviour for the latest versions is enough.