Quiero obtener un conjunto de consultas de todos los trabajos que se encuentran dentro de una distancia determinada de al menos una de las muchas ubicaciones proporcionadas, ordenarlos por la distancia mínima y no mostrar trabajos duplicados.
from django.db import models from cities.models import City class Job(models.Model): title = models.CharField(max_length=255) cities = models.ManyToManyField(City)Si solo hay un punto, podría hacer esto como:
from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.geos import Point point = Point(x, y, srid=4326) Job.objects.filter(cities__location__dwithin=(point, dist)) \ .annotate(distance=Distance("cities__location", point) \ .order_by('distance')pero cuando tengo muchos puntos, construyo una expresión Q para el filtro, pero no estoy seguro de una forma limpia de anotar la distancia mínima del trabajo a todos los puntos
query = Q() for point in points: query |= Q(cities__location__dwithin=(point, dist)) Job.objects.filter(query).annotate(distance=Min(...)).order_by('distance')FYI usando postgres 12.1 con extensión PostGIS
query = Q() distances = [] for point in points: query |= Q(cities__location__dwithin=(point, dist)) distances.append(Distance("cities__location", point)) # LEAST requires 2 or more expressions, MIN works for single expression if len(distances) == 1: MIN_FUNC = Min else: MIN_FUNC = Least Job.objects.filter(query).annotate(distance=MIN_FUNC(*distances)).order_by('distance')MIN es una función de agregación que toma una sola expresión, como un nombre de columna, y reduce múltiples entradas a un solo valor de salidaLEAST es una expresión condicional que funciona seleccionando el valor más pequeño de una lista de cualquier número de expresioneshttps://docs.djangoproject.com/en/3.0/ref/models/querysets/#min https://docs.djangoproject.com/en/3.0/ref/models/database-functions/#menos