Frage

Mit der Entfernung Logik von , ich bin immer eine richtig gefilterten Reihe von Objekten mit diesem Code zurück:

class LocationManager(models.Manager):
    def nearby_locations(self, latitude, longitude, radius, max_results=100, use_miles=True):
        if use_miles:
            distance_unit = 3959
        else:
            distance_unit = 6371

        from django.db import connection, transaction
        cursor = connection.cursor()

        sql = """SELECT id, (%f * acos( cos( radians(%f) ) * cos( radians( latitude ) ) *
        cos( radians( longitude ) - radians(%f) ) + sin( radians(%f) ) * sin( radians( latitude ) ) ) )
        AS distance FROM locations_location HAVING distance < %d
        ORDER BY distance LIMIT 0 , %d;""" % (distance_unit, latitude, longitude, latitude, int(radius), max_results)
        cursor.execute(sql)
        ids = [row[0] for row in cursor.fetchall()]

        return self.filter(id__in=ids)

Das Problem ist, ich kann nicht herausfinden, wie die Liste zu halten / queryset durch den Abstandswert sortiert. Ich mag nicht aus Leistungsgründen dies als zusätzlichem () -Methode tun (eine Abfrage im Vergleich zu einer Abfrage auf jeder möglichen Position in der Datenbank). Ein paar Fragen:

  1. Wie kann ich meine Liste nach Entfernung sortiert werden? Auch die einheimische Art auszuziehen ich in meinem Modell definiert habe und mit „order_by ()“, noch durch etwas andere Sortierung ist (id, glaube ich).
  2. Bin ich falsch über die Leistung Sache und Django wird die Abfrage optimieren, so sollte ich zusätzliche verwenden () statt?
  3. Ist das der völlig falsche Weg, dies zu tun, und ich soll die geo-Bibliothek verwenden, anstatt von Hand rollt dies wie ein putz?
War es hilfreich?

Lösung

Um Ihre Fragen in umgekehrter Reihenfolge:

Re 3) Ja, Sie sollten auf jeden Fall nutzen PostGIS und GeoDjango nehmen, wenn Sie mit Erdbeobachtungsdaten arbeiten. Es ist einfach dumm, nicht zu.

Re 2) Ich glaube nicht, dass Sie ganz Django bekommen könnten diese Abfrage für Sie tun .extra mit () (Sperrung Annahme von dieses Ticket ), aber es ist ein ausgezeichneter Kandidat für die neue .RAW () -Methode in Django 1.2 (siehe unten).

Re 1) Sie erhalten eine Liste der IDs von Ihrer ersten Abfrage und dann eine „in“ Abfrage mit einem QuerySet der Objekte zu bekommen, um diese IDs entsprechen. Ihre zweite Abfrage hat keinen Zugriff auf den berechneten Abstand von der ersten Abfrage; es ist nur eine Liste von IDs zu holen (und es kümmert sich nicht darum, was Sie diese IDs in entweder bietet Reihenfolge).

Mögliche Lösungen (kurz all diese Notwasserung und mit GeoDjango):

  1. Upgrade auf Django 1.2 beta und verwenden Sie die neue .RAW () Methode . Dies ermöglicht Django auf intelligente Weise die Ergebnisse einer rohen SQL-Abfrage zu interpretieren und sie in eine QuerySet der tatsächlichen Modellobjekte drehen. Welches wäre Ihre aktuellen zwei Abfragen in eine, reduzieren und die Bestellung Sie in SQL angeben bewahren. Dies ist die beste Option, wenn Sie sind in der Lage das Upgrade zu machen.

  2. Do not bother eine Django queryset oder Django Modell-Objekte überhaupt konstruieren, fügen Sie einfach alle die Felder, die Sie in die rohe SQL SELECT müssen und dann die Zeilen aus dem Cursor direkt verwenden. Kann keine Option sein, wenn Sie Methoden usw. später Modell benötigen.

  3. Führen Sie einen dritten Schritt in Python-Code, wo Sie Iterierte über die queryset und konstruiert eine Python-Liste von Modellobjekten in der gleichen Reihenfolge wie die Ide Listen Sie zurück von der ersten Abfrage bekommen. Bringe diese Liste anstelle eines QuerySet. Wird nicht funktionieren, wenn Sie eine weitere Filterung auf der ganzen Linie zu tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top