Merge branch 'elemmatch' of https://github.com/wpjunior/mongoengine into elemmatch
This commit is contained in:
		| @@ -640,6 +640,7 @@ class QuerySet(object): | |||||||
|         match_operators = ['contains', 'icontains', 'startswith', |         match_operators = ['contains', 'icontains', 'startswith', | ||||||
|                            'istartswith', 'endswith', 'iendswith', |                            'istartswith', 'endswith', 'iendswith', | ||||||
|                            'exact', 'iexact'] |                            'exact', 'iexact'] | ||||||
|  |         custom_operators = ['match'] | ||||||
|  |  | ||||||
|         mongo_query = {} |         mongo_query = {} | ||||||
|         for key, value in query.items(): |         for key, value in query.items(): | ||||||
| @@ -652,7 +653,7 @@ class QuerySet(object): | |||||||
|             parts = [part for part in parts if not part.isdigit()] |             parts = [part for part in parts if not part.isdigit()] | ||||||
|             # Check for an operator and transform to mongo-style if there is |             # Check for an operator and transform to mongo-style if there is | ||||||
|             op = None |             op = None | ||||||
|             if parts[-1] in operators + match_operators + geo_operators: |             if parts[-1] in operators + match_operators + geo_operators + custom_operators: | ||||||
|                 op = parts.pop() |                 op = parts.pop() | ||||||
|  |  | ||||||
|             negate = False |             negate = False | ||||||
| @@ -685,7 +686,7 @@ class QuerySet(object): | |||||||
|                     if isinstance(field, basestring): |                     if isinstance(field, basestring): | ||||||
|                         if op in match_operators and isinstance(value, basestring): |                         if op in match_operators and isinstance(value, basestring): | ||||||
|                             from mongoengine import StringField |                             from mongoengine import StringField | ||||||
|                             value = StringField().prepare_query_value(op, value) |                             value = StringField.prepare_query_value(op, value) | ||||||
|                         else: |                         else: | ||||||
|                             value = field |                             value = field | ||||||
|                     else: |                     else: | ||||||
| @@ -693,7 +694,8 @@ class QuerySet(object): | |||||||
|                 elif op in ('in', 'nin', 'all', 'near'): |                 elif op in ('in', 'nin', 'all', 'near'): | ||||||
|                     # 'in', 'nin' and 'all' require a list of values |                     # 'in', 'nin' and 'all' require a list of values | ||||||
|                     value = [field.prepare_query_value(op, v) for v in value] |                     value = [field.prepare_query_value(op, v) for v in value] | ||||||
|  |                  | ||||||
|  |                  | ||||||
|             # if op and op not in match_operators: |             # if op and op not in match_operators: | ||||||
|             if op: |             if op: | ||||||
|                 if op in geo_operators: |                 if op in geo_operators: | ||||||
| @@ -712,6 +714,12 @@ class QuerySet(object): | |||||||
|                     else: |                     else: | ||||||
|                         raise NotImplementedError("Geo method '%s' has not " |                         raise NotImplementedError("Geo method '%s' has not " | ||||||
|                                                   "been implemented" % op) |                                                   "been implemented" % op) | ||||||
|  |                 elif op in custom_operators: | ||||||
|  |                     if op == 'match': | ||||||
|  |                         value = {"$elemMatch": value} | ||||||
|  |                     else: | ||||||
|  |                         NotImplementedError("Custom method '%s' has not " | ||||||
|  |                                             "been implemented" % op) | ||||||
|                 elif op not in match_operators: |                 elif op not in match_operators: | ||||||
|                     value = {'$' + op: value} |                     value = {'$' + op: value} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2866,6 +2866,29 @@ class QueryFieldListTest(unittest.TestCase): | |||||||
|         q += QueryFieldList(fields=['a'], value={"$slice": 5}) |         q += QueryFieldList(fields=['a'], value={"$slice": 5}) | ||||||
|         self.assertEqual(q.as_dict(), {'a': {"$slice": 5}}) |         self.assertEqual(q.as_dict(), {'a': {"$slice": 5}}) | ||||||
|  |  | ||||||
|  |     def test_elem_match(self): | ||||||
|  |         class Foo(EmbeddedDocument): | ||||||
|  |             shape = StringField() | ||||||
|  |             color = StringField() | ||||||
|  |             trick = BooleanField()                 | ||||||
|  |             meta = {'allow_inheritance': False} | ||||||
|  |  | ||||||
|  |         class Bar(Document): | ||||||
|  |             foo = ListField(EmbeddedDocumentField(Foo)) | ||||||
|  |             meta = {'allow_inheritance': False} | ||||||
|  |  | ||||||
|  |         Bar.drop_collection() | ||||||
|  |          | ||||||
|  |         b1 = Bar(foo=[Foo(shape= "square", color ="purple", thick = False), | ||||||
|  |                       Foo(shape= "circle", color ="red", thick = True)]) | ||||||
|  |         b1.save() | ||||||
|  |  | ||||||
|  |         b2 = Bar(foo=[Foo(shape= "square", color ="red", thick = True), | ||||||
|  |                       Foo(shape= "circle", color ="purple", thick = False)]) | ||||||
|  |         b2.save() | ||||||
|  |          | ||||||
|  |         ak = list(Bar.objects(foo__match={'shape': "square", "color": "purple"})) | ||||||
|  |         self.assertEqual([b1], ak) | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user