Skip to content

Conversation

@NoahStapp
Copy link
Contributor

@NoahStapp NoahStapp commented Nov 19, 2025

@NoahStapp
Copy link
Contributor Author

All tests (including some simple ones I added due to many of the Django ones requiring features we don't support) passing, marking as ready for an initial review pass.

@NoahStapp NoahStapp marked this pull request as ready for review November 20, 2025 22:16
timgraham

This comment was marked as resolved.

@timgraham timgraham changed the title Initial GeoSpatial query support INTPYTHON-835 Add support for GIS lookups Nov 21, 2025
@NoahStapp NoahStapp requested a review from timgraham November 24, 2025 16:06
timgraham

This comment was marked as resolved.

@timgraham

This comment was marked as resolved.

@NoahStapp

This comment was marked as resolved.

@NoahStapp NoahStapp requested review from WaVEV and timgraham and removed request for timgraham December 1, 2025 14:21
@NoahStapp NoahStapp requested a review from timgraham December 5, 2025 14:26
Jibola
Jibola previously requested changes Dec 16, 2025
Comment on lines 55 to 67
if self.name == "distance_gt" or self.name == "distance_gte":
cmd = {
field: {
"$not": {
"$geoWithin": {
"$centerSphere": [
value["coordinates"],
distance / 6378100, # radius of earth in meters
],
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be moved to DistanceGT and DistanceGTE

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you be more specific? Having it here lets us reduce the code duplication.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see a refactor like this: [Incidentally, is gt vs. gte accounted for elsewhere?)

diff --git a/django_mongodb_backend/gis/operators.py b/django_mongodb_backend/gis/operators.py
index cc24473..3824de5 100644
--- a/django_mongodb_backend/gis/operators.py
+++ b/django_mongodb_backend/gis/operators.py
@@ -52,22 +52,28 @@ class DistanceBase(Operator):
 
     def as_mql(self, field, value, params=None):
         distance = params[0].m if hasattr(params[0], "m") else params[0]
-        if self.name == "distance_gt" or self.name == "distance_gte":
-            cmd = {
-                field: {
-                    "$not": {
-                        "$geoWithin": {
-                            "$centerSphere": [
-                                value["coordinates"],
-                                distance / 6378100,  # radius of earth in meters
-                            ],
-                        }
-                    }
+        return self.get_mql(field, value, distance):
+
+    def get_mql(self, field, value, distance):
+        return  {
+            field: {
+                "$geoWithin": {
+                    "$centerSphere": [
+                        value["coordinates"],
+                        distance / 6378100,  # radius of earth in meters
+                    ],
                 }
             }
+        return self.get_mql(field, value, distance):
+
+    def get_mql(self, field, value, distance):
+        return  {
+            field: {
+                "$geoWithin": {
+                    "$centerSphere": [
+                        value["coordinates"],
+                        distance / 6378100,  # radius of earth in meters
+                    ],
                 }
             }
-        else:
-            cmd = {
-                field: {
+        }
+
+
+class DistanceGT(DistanceBase):
+    name = "distance_gt"
+
+    def get_mql(self, field, value, distance):
+        return {
+            field: {
+                "$not": {
                     "$geoWithin": {
                         "$centerSphere": [
                             value["coordinates"],
@@ -76,14 +82,9 @@ class DistanceBase(Operator):
                     }
                 }
             }
-        return cmd
-
-
-class DistanceGT(DistanceBase):
-    name = "distance_gt"
-
+        }
 
-class DistanceGTE(DistanceBase):
+class DistanceGTE(DistanceGT):
     name = "distance_gte"
 
 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The geospatial functionality supported by the server doesn't allow for a finer-grained gt vs gte filter beyond adding a tiny offset to the given distance. We could add that, but then we are effectively modifying user queries invisibly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that only one of gt/gte is really supported then, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put that way yes, we don't support strict LT or GT. Removing those two operators would be clearer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like only one of LT or GT should be "equal to". Since the query condition is negated, both can't include the "equal to" boundary, right?

Copy link
Contributor Author

@NoahStapp NoahStapp Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. We'll have to arbitrarily pick one to be equal to and one to be strictly less/greater. Since greater than is the negation, that will be the strict (no equal to) operation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI (if correct) says "The $geoWithin operator treats its border as inclusive" so I think it would be lte and gt.

value = value[0]
if isinstance(value, Distance):
raise ValueError(
"Only numeric values of radian units are allowed on geodetic distance queries."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think saying "geodetic" isn't necessary because MongoDB doesn't support non-geodetic. Also, unlike the SQL implementation, this method isn't used for distance queries, rather it should say "on dwithin queries", I believe.

@NoahStapp NoahStapp requested a review from timgraham January 7, 2026 14:47
@timgraham timgraham changed the title INTPYTHON-835 Add support for GIS lookups INTPYTHON-835 Add support for spatial lookups Jan 8, 2026
@timgraham timgraham dismissed Jibola’s stale review January 8, 2026 22:29

changes addressed

@timgraham timgraham merged commit 3059abc into mongodb:main Jan 8, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants