質問

からの距離ロジックを使用する このSO投稿, このコードを使用すると、適切にフィルタリングされたオブジェクトのセットが返されます。

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)

問題は、距離値によってリスト/クエリセットを並べ替える方法がわからないことです。パフォーマンス上の理由から、これを extra() メソッド呼び出しとして実行したくありません (データベース内の各潜在的な場所に対して 1 つのクエリと 1 つのクエリ)。いくつかの質問:

  1. リストを距離順に並べ替えるにはどうすればよいですか?モデルで定義したネイティブの並べ替えを外して「order_by()」を使用しても、依然として別の何か (ID だと思います) によって並べ替えられています。
  2. パフォーマンスに関する私は間違っていて、Django がクエリを最適化するので、代わりに extra() を使用する必要がありますか?
  3. これは完全に間違った方法で、パッツのように手で転がすのではなく、地理ライブラリを使用する必要がありますか?
役に立ちましたか?

解決

質問を逆の順序で受けるには:

Re 3) はい、地理空間データを扱う場合は、PostGIS と GeoDjango をぜひ活用してください。そうしないのは愚かです。

Re 2) .extra() を使用して Django にこのクエリを実行させることはできないと思います (ただし、 このチケット) ですが、これは Django 1.2 の新しい .raw() メソッドの優れた候補です (下記を参照)。

Re 1) 最初のクエリから ID のリストを取得し、「in」クエリを使用してそれらの ID に対応するオブジェクトの QuerySet を取得します。2 番目のクエリは、最初のクエリから計算された距離にアクセスできません。ID のリストを取得するだけです (ID を指定する順序も気にしません)。

考えられる解決策 (これをすべて捨てて GeoDjango を使用する以外):

  1. Django 1.2 ベータ版にアップグレードして、 新しい .raw() メソッド. 。これにより、Django は生の SQL クエリの結果をインテリジェントに解釈し、それを実際のモデル オブジェクトの QuerySet に変換できます。これにより、現在の 2 つのクエリが 1 つに減り、SQL で指定した順序が維持されます。アップグレードできる場合は、これが最良のオプションです。

  2. Django クエリセットや Django モデル オブジェクトをわざわざ構築する必要はまったくありません。必要なフィールドをすべて生の SQL SELECT に追加し、それらの行をカーソルから直接使用するだけです。後でモデルメソッドなどが必要になる場合は、オプションではない可能性があります。

  3. Python コードで 3 番目のステップを実行します。ここでは、クエリセットを反復処理し、最初のクエリから返された ID リストと同じ順序でモデル オブジェクトの Python リストを構築します。QuerySet の代わりにそのリストを返します。今後さらにフィルタリングを行う必要がある場合は機能しません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top