Skip to content

Commit 04c7582

Browse files
committed
edits
1 parent d61cbff commit 04c7582

File tree

6 files changed

+39
-61
lines changed

6 files changed

+39
-61
lines changed

django_mongodb/compiler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,8 @@ def collection_name(self):
442442
if isinstance(v, BaseTable) and self.query.alias_refcount[k]
443443
)
444444
except StopIteration:
445-
# If the query does not have any table, collection '__null' is used
446-
# with one document in order to support subqueries and expressions.
445+
# Use a dummy collection if the query doesn't specify a table
446+
# (such as Constraint.validate() with a condition).
447447
query = self.query_class(self)
448448
query.aggregation_pipeline = [{"$facet": {"__null": []}}]
449449
self.subqueries.insert(0, query)

django_mongodb/expressions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def case(self, compiler, connection):
5353
def col(self, compiler, connection): # noqa: ARG001
5454
# If the column is part of a subquery and belongs to one of the parent
5555
# queries, it will be stored for reference using $let in a $lookup stage.
56-
# If the query is built with `alias_cols=False`, the column is treated
57-
# as belonging to the current collection.
56+
# If the query is built with `alias_cols=False`, treat the column as
57+
# belonging to the current collection.
5858
if self.alias is not None and (
5959
self.alias not in compiler.query.alias_refcount
6060
or compiler.query.alias_refcount[self.alias] == 0

django_mongodb/features.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
2323
supports_expression_indexes = False
2424
supports_foreign_keys = False
2525
supports_ignore_conflicts = False
26+
# Before MongoDB 6.0, $in cannot be used in partialFilterExpression.
2627
supports_in_index_operator = property(operator.attrgetter("is_mongodb_6_0"))
28+
# Before MongoDB 6.0, $or cannot be used in partialFilterExpression.
29+
supports_or_index_operator = property(operator.attrgetter("is_mongodb_6_0"))
2730
supports_json_field_contains = False
2831
# BSON Date type doesn't support microsecond precision.
2932
supports_microsecond_precision = False
@@ -97,7 +100,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
97100
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_right_null",
98101
"expressions.tests.ExpressionOperatorTests.test_lefthand_transformed_field_bitwise_or",
99102
}
100-
# Before MongoDB 6.0, $in cannot be used in partialFilterExpression.
101103
_django_test_expected_failures_partial_expression_in = {
102104
"schema.tests.SchemaTests.test_remove_ignored_unique_constraint_not_create_fk_index",
103105
}
@@ -106,7 +108,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
106108
def django_test_expected_failures(self):
107109
expected_failures = super().django_test_expected_failures
108110
expected_failures.update(self._django_test_expected_failures)
109-
if not self.is_mongodb_6_0:
111+
if not self.supports_in_index_operator:
110112
expected_failures.update(self._django_test_expected_failures_partial_expression_in)
111113
if not self.is_mongodb_6_3:
112114
expected_failures.update(self._django_test_expected_failures_bitwise)

django_mongodb/indexes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .query_utils import process_rhs
99

10-
mongo_operators_idx = {
10+
MONGO_INDEX_OPERATORS = {
1111
"exact": "$eq",
1212
"gt": "$gt",
1313
"gte": "$gte",
@@ -29,7 +29,7 @@ def builtin_lookup_idx(self, compiler, connection):
2929
lhs_mql = self.lhs.target.column
3030
value = process_rhs(self, compiler, connection)
3131
try:
32-
operator = mongo_operators_idx[self.lookup_name]
32+
operator = MONGO_INDEX_OPERATORS[self.lookup_name]
3333
except KeyError:
3434
raise NotSupportedError(
3535
f"MongoDB does not support the '{self.lookup_name}' lookup in indexes."

tests/indexes_/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
class Article(models.Model):
55
headline = models.CharField(max_length=100)
66
number = models.IntegerField()
7-
body = models.CharField(max_length=100)
7+
body = models.TextField()

tests/indexes_/test_mql.py renamed to tests/indexes_/test_condition.py

Lines changed: 28 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,24 @@
88

99

1010
class PartialIndexTests(TestCase):
11+
def assertAddRemoveIndex(self, editor, model, index):
12+
editor.add_index(index=index, model=model)
13+
self.assertIn(
14+
index.name,
15+
connection.introspection.get_constraints(
16+
cursor=None,
17+
table_name=model._meta.db_table,
18+
),
19+
)
20+
editor.remove_index(index=index, model=model)
21+
1122
def test_not_supported(self):
1223
msg = "MongoDB does not support the 'isnull' lookup in indexes."
1324
with connection.schema_editor() as editor, self.assertRaisesMessage(NotSupportedError, msg):
1425
Index(
15-
name="not_supported",
26+
name="test",
1627
fields=["headline"],
17-
condition=Q(pk__isnull=True) & Q(pk__contains="test1"),
28+
condition=Q(pk__isnull=True),
1829
)._get_condition_mql(Article, schema_editor=editor)
1930

2031
def test_negated_not_supported(self):
@@ -35,7 +46,7 @@ def test_xor_not_supported(self):
3546
condition=Q(pk=True) ^ Q(pk=False),
3647
)._get_condition_mql(Article, schema_editor=editor)
3748

38-
@skipIfDBFeature("supports_in_index_operator")
49+
@skipIfDBFeature("supports_or_index_operator")
3950
def test_or_not_supported(self):
4051
msg = "MongoDB < 6.0 does not support the '|' operator in indexes."
4152
with self.assertRaisesMessage(NotSupportedError, msg), connection.schema_editor() as editor:
@@ -59,11 +70,10 @@ def test_in_not_supported(self):
5970
def test_composite_index(self):
6071
with connection.schema_editor() as editor:
6172
index = Index(
62-
name="composite_proposition",
73+
name="test",
6374
fields=["headline"],
6475
condition=Q(number__gte=3) & (Q(body__gt="test1") | Q(body__in=["A", "B"])),
6576
)
66-
index._get_condition_mql(Article, schema_editor=editor)
6777
self.assertEqual(
6878
index._get_condition_mql(Article, schema_editor=editor),
6979
{
@@ -73,78 +83,44 @@ def test_composite_index(self):
7383
]
7484
},
7585
)
76-
editor.add_index(index=index, model=Article)
77-
with connection.cursor() as cursor:
78-
self.assertIn(
79-
index.name,
80-
connection.introspection.get_constraints(
81-
cursor=cursor,
82-
table_name=Article._meta.db_table,
83-
),
84-
)
85-
editor.remove_index(index=index, model=Article)
86+
self.assertAddRemoveIndex(editor, Article, index)
8687

8788
def test_composite_op_index(self):
8889
operators = (
89-
(
90-
(operator.or_, "$or"),
91-
(operator.and_, "$and"),
92-
)
93-
if connection.features.supports_in_index_operator
94-
else ((operator.and_, "$and"),)
90+
(operator.or_, "$or"),
91+
(operator.and_, "$and"),
9592
)
93+
if not connection.features.supports_or_index_operator:
94+
operators = operators[1:]
9695
for op, mongo_operator in operators:
9796
with self.subTest(operator=op), connection.schema_editor() as editor:
9897
index = Index(
99-
name="composite_proposition",
98+
name="test",
10099
fields=["headline"],
101100
condition=op(Q(number__gte=3), Q(body__gt="test1")),
102101
)
103-
index._get_condition_mql(Article, schema_editor=editor)
104-
target = {mongo_operator: [{"number": {"$gte": 3}}, {"body": {"$gt": "test1"}}]}
105102
self.assertEqual(
106-
target,
103+
{mongo_operator: [{"number": {"$gte": 3}}, {"body": {"$gt": "test1"}}]},
107104
index._get_condition_mql(Article, schema_editor=editor),
108105
)
109-
editor.add_index(index=index, model=Article)
110-
with connection.cursor() as cursor:
111-
self.assertIn(
112-
index.name,
113-
connection.introspection.get_constraints(
114-
cursor=cursor,
115-
table_name=Article._meta.db_table,
116-
),
117-
)
118-
editor.remove_index(index=index, model=Article)
106+
self.assertAddRemoveIndex(editor, Article, index)
119107

120108
def test_simple_operations(self):
121-
mongo_operators_idx = (
109+
operators = (
122110
("gt", "$gt"),
123111
("gte", "$gte"),
124112
("lt", "$lt"),
125113
("lte", "$lte"),
126114
)
127-
128-
for op, mongo_operator in mongo_operators_idx:
115+
for op, mongo_operator in operators:
129116
with self.subTest(operator=op), connection.schema_editor() as editor:
130117
index = Index(
131-
name="composite_proposition",
118+
name="test",
132119
fields=["headline"],
133120
condition=Q(**{f"number__{op}": 3}),
134121
)
135-
index._get_condition_mql(Article, schema_editor=editor)
136-
target = {"number": {mongo_operator: 3}}
137122
self.assertEqual(
138-
target,
123+
{"number": {mongo_operator: 3}},
139124
index._get_condition_mql(Article, schema_editor=editor),
140125
)
141-
editor.add_index(index=index, model=Article)
142-
with connection.cursor() as cursor:
143-
self.assertIn(
144-
index.name,
145-
connection.introspection.get_constraints(
146-
cursor=cursor,
147-
table_name=Article._meta.db_table,
148-
),
149-
)
150-
editor.remove_index(index=index, model=Article)
126+
self.assertAddRemoveIndex(editor, Article, index)

0 commit comments

Comments
 (0)