diff --git a/django_mongodb/base.py b/django_mongodb/base.py index 4a48d873..3c1a8bc8 100644 --- a/django_mongodb/base.py +++ b/django_mongodb/base.py @@ -100,8 +100,10 @@ def _isnull_operator(a, b): "exact": lambda a, b: {"$eq": [a, b]}, "gt": lambda a, b: {"$gt": [a, b]}, "gte": lambda a, b: {"$gte": [a, b]}, - "lt": lambda a, b: {"$lt": [a, b]}, - "lte": lambda a, b: {"$lte": [a, b]}, + # MongoDB considers null less than zero. Exclude null values to match + # SQL behavior. + "lt": lambda a, b: {"$and": [{"$lt": [a, b]}, {"$ne": [a, None]}]}, + "lte": lambda a, b: {"$and": [{"$lte": [a, b]}, {"$ne": [a, None]}]}, "in": lambda a, b: {"$in": [a, b]}, "isnull": _isnull_operator, "range": lambda a, b: { diff --git a/django_mongodb/features.py b/django_mongodb/features.py index 4e585242..5c3e3ea7 100644 --- a/django_mongodb/features.py +++ b/django_mongodb/features.py @@ -62,8 +62,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): # the result back to UTC. "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_func_with_timezone", "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_timezone_applied_before_truncation", - # Length of null considered zero rather than null. - "db_functions.text.test_length.LengthTests.test_basic", # Unexpected alias_refcount in alias_map. "queries.tests.Queries1Tests.test_order_by_tables", # The $sum aggregation returns 0 instead of None for null. diff --git a/tests/lookup_/__init__.py b/tests/lookup_/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/lookup_/models.py b/tests/lookup_/models.py new file mode 100644 index 00000000..dd0f1547 --- /dev/null +++ b/tests/lookup_/models.py @@ -0,0 +1,11 @@ +from django.db import models + + +class Number(models.Model): + num = models.IntegerField(blank=True, null=True) + + class Meta: + ordering = ("num",) + + def __str__(self): + return str(self.num) diff --git a/tests/lookup_/tests.py b/tests/lookup_/tests.py new file mode 100644 index 00000000..520976d1 --- /dev/null +++ b/tests/lookup_/tests.py @@ -0,0 +1,17 @@ +from django.test import TestCase + +from .models import Number + + +class NumericLookupTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.objs = Number.objects.bulk_create(Number(num=x) for x in range(5)) + # Null values should be excluded in less than queries. + Number.objects.create() + + def test_lt(self): + self.assertQuerySetEqual(Number.objects.filter(num__lt=3), self.objs[:3]) + + def test_lte(self): + self.assertQuerySetEqual(Number.objects.filter(num__lte=3), self.objs[:4])