16

Using geoDjango, what is the difference between

myObj.objects.filter(point__dwithin(...etc.))   

and

myObj.objects.filter(point__distance_lt(...etc.))  

?
Are they the same thing, or are they doing subtly different things?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
hendrixski
  • 1,124
  • 1
  • 12
  • 20

1 Answers1

32

Ok, I did some research but I don't know if the results are of any use ;)

  • I looked at the unit tests that they use to test the DB queries but they don't give real hints (to me).

  • I tried to compare the generated SQL:

I have already a geo application using a PostgreSQL databse. When I perform this query with __distance_lt:

Place.objects.filter(location__distance_lt=(p.location, D(km=1))).query.as_sql()

I get this generated SQL:

SELECT (some_fields_here)
FROM "places_place" 
WHERE ST_distance_sphere("places_place"."location", %s) < 1000.0

When I try to use do to the same with __dwithin, I get an error:

Place.objects.filter(location__dwithin=(p.location, D(km=1))).query.as_sql()

TypeError: Only numeric values of degree units are allowed on geographic DWithin queries.

So I had to change the query to no use a D object:

Place.objects.filter(location__dwithin=(p.location, 1)).query.as_sql()

which results in

SELECT (some fields here) 
FROM "places_place" 
WHERE ST_DWithin("places_place"."location", %s, 1)

Summary:

__dwithin
- takes degree values as distance parameter.
- uses ST_DWithin SQL function.

__distance_lt
- can take other distance values ;).
- uses ST_distance_sphere SQL function.

Btw, I get different results with both queries but I guess this is mostly due the fact that I don't know which "degree" value to use.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • hi! :) this is an extremely useful answer – djq Apr 30 '13 at 13:08
  • 2
    Note **dwithin** is fastest since it makes best use of the spatial index [see discussion here](http://stackoverflow.com/questions/7845133/how-can-i-query-all-my-data-within-a-distance-of-5-meters). – s29 May 27 '13 at 04:17
  • 1
    @FelixKling the dwithin value is in **metres**, per the [postgis docs](http://postgis.org/docs/ST_DWithin.html) – s29 May 27 '13 at 04:19
  • 2
    @s29: After looking at the documentation today (https://docs.djangoproject.com/en/dev/ref/contrib/gis/geoquerysets/#dwithin) it indeed looks like `dwithin` accepts distance objects now. Maybe the error message given was incorrect. I can only assume that this changed over the years. I will update my answer. Thanks! – Felix Kling May 27 '13 at 08:09