Skip to content

Commit 8ef7719

Browse files
committed
fixing incompatibility with mongoengine aggregation to support mongo 4.4
1 parent 2d1c9af commit 8ef7719

File tree

5 files changed

+31
-10
lines changed

5 files changed

+31
-10
lines changed

mongoengine/mongodb_support.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# get_mongodb_version()
99
MONGODB_34 = (3, 4)
1010
MONGODB_36 = (3, 6)
11+
MONGODB_44 = (4, 4)
1112

1213

1314
def get_mongodb_version():

mongoengine/queryset/base.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,21 +1355,18 @@ def map_reduce(
13551355

13561356
MapReduceDocument = _import_class("MapReduceDocument")
13571357

1358-
if not hasattr(self._collection, "map_reduce"):
1359-
raise NotImplementedError("Requires MongoDB >= 1.7.1")
1360-
13611358
map_f_scope = {}
13621359
if isinstance(map_f, Code):
13631360
map_f_scope = map_f.scope
13641361
map_f = str(map_f)
1365-
map_f = Code(queryset._sub_js_fields(map_f), map_f_scope)
1362+
map_f = Code(queryset._sub_js_fields(map_f), map_f_scope or None)
13661363

13671364
reduce_f_scope = {}
13681365
if isinstance(reduce_f, Code):
13691366
reduce_f_scope = reduce_f.scope
13701367
reduce_f = str(reduce_f)
13711368
reduce_f_code = queryset._sub_js_fields(reduce_f)
1372-
reduce_f = Code(reduce_f_code, reduce_f_scope)
1369+
reduce_f = Code(reduce_f_code, reduce_f_scope or None)
13731370

13741371
mr_args = {"query": queryset._query}
13751372

@@ -1379,7 +1376,7 @@ def map_reduce(
13791376
finalize_f_scope = finalize_f.scope
13801377
finalize_f = str(finalize_f)
13811378
finalize_f_code = queryset._sub_js_fields(finalize_f)
1382-
finalize_f = Code(finalize_f_code, finalize_f_scope)
1379+
finalize_f = Code(finalize_f_code, finalize_f_scope or None)
13831380
mr_args["finalize"] = finalize_f
13841381

13851382
if scope:

tests/document/test_indexes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from mongoengine import *
99
from mongoengine.connection import get_db
10+
from mongoengine.mongodb_support import MONGODB_44, get_mongodb_version
1011

1112

1213
class TestIndexes(unittest.TestCase):
@@ -452,9 +453,11 @@ class Test(Document):
452453
.get("stage")
453454
== "IXSCAN"
454455
)
456+
mongo_db = get_mongodb_version()
457+
PROJECTION_STR = "PROJECTION" if mongo_db < MONGODB_44 else "PROJECTION_COVERED"
455458
assert (
456459
query_plan.get("queryPlanner").get("winningPlan").get("stage")
457-
== "PROJECTION"
460+
== PROJECTION_STR
458461
)
459462

460463
query_plan = Test.objects(a=1).explain()

tests/queryset/test_queryset.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
QuerySetManager,
2222
queryset_manager,
2323
)
24-
from tests.utils import requires_mongodb_gte_44
24+
from tests.utils import (
25+
requires_mongodb_gte_44,
26+
requires_mongodb_lt_42,
27+
requires_mongodb_lte_42,
28+
)
2529

2630

2731
class db_ops_tracker(query_counter):
@@ -1490,6 +1494,7 @@ class BlogPost(Document):
14901494

14911495
BlogPost.drop_collection()
14921496

1497+
@requires_mongodb_lt_42
14931498
def test_exec_js_query(self):
14941499
"""Ensure that queries are properly formed for use in exec_js."""
14951500

@@ -1527,6 +1532,7 @@ class BlogPost(Document):
15271532

15281533
BlogPost.drop_collection()
15291534

1535+
@requires_mongodb_lt_42
15301536
def test_exec_js_field_sub(self):
15311537
"""Ensure that field substitutions occur properly in exec_js functions."""
15321538

@@ -3109,6 +3115,7 @@ class Person(Document):
31093115
freq = Person.objects.item_frequencies("city", normalize=True, map_reduce=True)
31103116
assert freq == {"CRB": 0.5, None: 0.5}
31113117

3118+
@requires_mongodb_lte_42
31123119
def test_item_frequencies_with_null_embedded(self):
31133120
class Data(EmbeddedDocument):
31143121
name = StringField()
@@ -3137,6 +3144,7 @@ class Person(Document):
31373144
ot = Person.objects.item_frequencies("extra.tag", map_reduce=True)
31383145
assert ot == {None: 1.0, "friend": 1.0}
31393146

3147+
@requires_mongodb_lte_42
31403148
def test_item_frequencies_with_0_values(self):
31413149
class Test(Document):
31423150
val = IntField()
@@ -3151,6 +3159,7 @@ class Test(Document):
31513159
ot = Test.objects.item_frequencies("val", map_reduce=False)
31523160
assert ot == {0: 1}
31533161

3162+
@requires_mongodb_lte_42
31543163
def test_item_frequencies_with_False_values(self):
31553164
class Test(Document):
31563165
val = BooleanField()
@@ -3165,6 +3174,7 @@ class Test(Document):
31653174
ot = Test.objects.item_frequencies("val", map_reduce=False)
31663175
assert ot == {False: 1}
31673176

3177+
@requires_mongodb_lte_42
31683178
def test_item_frequencies_normalize(self):
31693179
class Test(Document):
31703180
val = IntField()
@@ -3551,7 +3561,8 @@ class Book(Document):
35513561
Book.objects.create(title="The Stories", authors=[mark_twain, john_tolkien])
35523562

35533563
authors = Book.objects.distinct("authors")
3554-
assert authors == [mark_twain, john_tolkien]
3564+
authors_names = {author.name for author in authors}
3565+
assert authors_names == {mark_twain.name, john_tolkien.name}
35553566

35563567
def test_distinct_ListField_EmbeddedDocumentField_EmbeddedDocumentField(self):
35573568
class Continent(EmbeddedDocument):
@@ -3588,7 +3599,8 @@ class Book(Document):
35883599
assert country_list == [scotland, tibet]
35893600

35903601
continent_list = Book.objects.distinct("authors.country.continent")
3591-
assert continent_list == [europe, asia]
3602+
continent_list_names = {c.continent_name for c in continent_list}
3603+
assert continent_list_names == {europe.continent_name, asia.continent_name}
35923604

35933605
def test_distinct_ListField_ReferenceField(self):
35943606
class Bar(Document):

tests/utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ def get_as_pymongo(doc):
3434
return doc.__class__.objects.as_pymongo().get(id=doc.id)
3535

3636

37+
def requires_mongodb_lt_42(func):
38+
return _decorated_with_ver_requirement(func, (4, 2), oper=operator.lt)
39+
40+
41+
def requires_mongodb_lte_42(func):
42+
return _decorated_with_ver_requirement(func, (4, 2), oper=operator.le)
43+
44+
3745
def requires_mongodb_gte_44(func):
3846
return _decorated_with_ver_requirement(func, (4, 4), oper=operator.ge)
3947

0 commit comments

Comments
 (0)