2

この 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. これは完全に間違った方法ですか? putz のように手動でロールするのではなく、geo ライブラリを使用する必要がありますか?
4

1 に答える 1

1

質問を逆の順序で行うには:

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 番目のステップを実行します。ここでは、クエリセットを反復処理し、モデル オブジェクトの Python リストを、最初のクエリから取得した ID リストと同じ順序で作成します。QuerySet の代わりにそのリストを返します。さらにフィルタリングを行う必要がある場合は機能しません。

于 2010-02-16T20:24:47.190 に答える