Skip to content

Commit 01c34a9

Browse files
committed
Add features.supports_in_index_operator flag.
1 parent 5565902 commit 01c34a9

File tree

3 files changed

+29
-20
lines changed

3 files changed

+29
-20
lines changed

django_mongodb/features.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import operator
2+
13
from django.db.backends.base.features import BaseDatabaseFeatures
24
from django.utils.functional import cached_property
35

@@ -21,6 +23,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
2123
supports_expression_indexes = False
2224
supports_foreign_keys = False
2325
supports_ignore_conflicts = False
26+
supports_in_index_operator = property(operator.attrgetter("is_mongodb_6_0"))
2427
supports_json_field_contains = False
2528
# BSON Date type doesn't support microsecond precision.
2629
supports_microsecond_precision = False

django_mongodb/indexes.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ def builtin_lookup_idx(self, compiler, connection):
3333
lhs_mql = self.lhs.target.column
3434
value = process_rhs(self, compiler, connection)
3535
try:
36-
return mongo_operators_idx[self.lookup_name](lhs_mql, value)
36+
operator = mongo_operators_idx[self.lookup_name]
3737
except KeyError:
3838
raise NotSupportedError(
3939
f"MongoDB does not support the '{self.lookup_name}' lookup in indexes."
4040
) from None
41+
return {lhs_mql: {operator: value}}
4142

4243

4344
def in_idx(self, compiler, connection):
44-
if not connection.features.is_mongodb_6_0:
45+
if not connection.features.supports_in_index_operator:
4546
raise NotSupportedError(
46-
f"MongoDB does not support the {self.lookup_name} lookup in indexes."
47+
f"MongoDB < 6.0 does not support the {self.lookup_name} lookup in indexes."
4748
)
4849
return builtin_lookup_idx(self, compiler, connection)
4950

@@ -56,13 +57,13 @@ def where_node_idx(self, compiler, connection):
5657
if self.connector == AND:
5758
operator = "$and"
5859
elif self.connector == XOR:
59-
raise NotSupportedError("MongoDB does not support the 'Xor' lookup in indexes.")
60+
raise NotSupportedError("MongoDB does not support the '^' operator lookup in indexes.")
6061
else:
61-
if not connection.features.is_mongodb_6_0:
62-
raise NotSupportedError("MongoDB does not support the 'Or' lookup in indexes.")
62+
if not connection.features.supports_in_index_operator:
63+
raise NotSupportedError("MongoDB < 6.0 does not support the '|' operator in indexes.")
6364
operator = "$or"
6465
if self.negated:
65-
raise NotSupportedError("MongoDB does not support negated field in indexes.")
66+
raise NotSupportedError("MongoDB does not support the '~' operator in indexes.")
6667
children_mql = []
6768
for child in self.children:
6869
try:

tests/indexes_/test_mql.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def test_not_supported(self):
1818
)._get_condition_mql(Article, schema_editor=editor)
1919

2020
def test_negated_not_supported(self):
21-
msg = "MongoDB does not support negated field in indexes."
21+
msg = "MongoDB does not support the '~' operator in indexes."
2222
with self.assertRaisesMessage(NotSupportedError, msg), connection.schema_editor() as editor:
2323
Index(
2424
name="test",
@@ -27,15 +27,15 @@ def test_negated_not_supported(self):
2727
)._get_condition_mql(Article, schema_editor=editor)
2828

2929
def test_xor_not_supported(self):
30-
msg = "MongoDB does not support the 'Xor' lookup in indexes."
30+
msg = "MongoDB does not support the '^' operator lookup in indexes."
3131
with self.assertRaisesMessage(NotSupportedError, msg), connection.schema_editor() as editor:
3232
Index(
3333
name="test",
3434
fields=["headline"],
3535
condition=Q(pk=True) ^ Q(pk=False),
3636
)._get_condition_mql(Article, schema_editor=editor)
3737

38-
@skipIfDBFeature("is_mongodb_6_0")
38+
@skipIfDBFeature("supports_in_index_operator")
3939
def test_or_not_supported(self):
4040
msg = "MongoDB does not support the 'Or' lookup in indexes."
4141
with self.assertRaisesMessage(NotSupportedError, msg), connection.schema_editor() as editor:
@@ -45,7 +45,7 @@ def test_or_not_supported(self):
4545
condition=Q(pk=True) | Q(pk=False),
4646
)._get_condition_mql(Article, schema_editor=editor)
4747

48-
@skipIfDBFeature("is_mongodb_6_0")
48+
@skipIfDBFeature("supports_in_index_operator")
4949
def test_in_not_supported(self):
5050
msg = "MongoDB does not support the 'in' lookup in indexes."
5151
with self.assertRaisesMessage(NotSupportedError, msg), connection.schema_editor() as editor:
@@ -55,21 +55,21 @@ def test_in_not_supported(self):
5555
condition=Q(pk__in=[True]),
5656
)._get_condition_mql(Article, schema_editor=editor)
5757

58-
@skipUnlessDBFeature("is_mongodb_6_0")
58+
@skipUnlessDBFeature("supports_in_index_operator")
5959
def test_composite_index(self):
6060
with connection.schema_editor() as editor:
6161
index = Index(
6262
name="composite_proposition",
6363
fields=["headline"],
64-
condition=Q(number__gte=3) & (Q(text__gt="test1") | Q(text__in=["A", "B"])),
64+
condition=Q(number__gte=3) & (Q(body__gt="test1") | Q(body__in=["A", "B"])),
6565
)
6666
index._get_condition_mql(Article, schema_editor=editor)
6767
self.assertEqual(
6868
index._get_condition_mql(Article, schema_editor=editor),
6969
{
7070
"$and": [
7171
{"number": {"$gte": 3}},
72-
{"$or": [{"text": {"$gt": "test1"}}, {"text": {"$in": ["A", "B"]}}]},
72+
{"$or": [{"body": {"$gt": "test1"}}, {"body": {"$in": ["A", "B"]}}]},
7373
]
7474
},
7575
)
@@ -85,18 +85,23 @@ def test_composite_index(self):
8585
editor.remove_index(index=index, model=Article)
8686

8787
def test_composite_op_index(self):
88-
for op in (
89-
[operator.or_, operator.and_] if connection.features.is_mongodb_6_0 else [operator.and_]
90-
):
88+
operators = (
89+
(
90+
(operator.or_, "$or"),
91+
(operator.and_, "$and"),
92+
)
93+
if connection.features.supports_in_index_operator
94+
else ((operator.and_, "$and"),)
95+
)
96+
for op, mongo_operator in operators:
9197
with self.subTest(operator=op), connection.schema_editor() as editor:
9298
index = Index(
9399
name="composite_proposition",
94100
fields=["headline"],
95-
condition=op(Q(number__gte=3), Q(text__gt="test1")),
101+
condition=op(Q(number__gte=3), Q(body__gt="test1")),
96102
)
97103
index._get_condition_mql(Article, schema_editor=editor)
98-
mongo_operator = "$and" if op == operator.and_ else "$or"
99-
target = {mongo_operator: [{"number": {"$gte": 3}}, {"text": {"$gt": "test1"}}]}
104+
target = {mongo_operator: [{"number": {"$gte": 3}}, {"body": {"$gt": "test1"}}]}
100105
self.assertEqual(
101106
target,
102107
index._get_condition_mql(Article, schema_editor=editor),

0 commit comments

Comments
 (0)