2016-05-13 9 views
0

ich folgendes Nearest Neighbor-Abfrage in PostGIS mit Flask-SQLAlchemy mit:Wie optimiert man die nächste Nachbarschaftsabfrage in Postgis innerhalb einer gegebenen Entfernung?

def get_neighbor(): 
    pt = WKTElement('POINT(%s %s)' % (longitude, latitude), srid=srid) 

    # Get total count of neighbor with distance less than 1000m for example. 
    total_count = db.session.query(User, func.ST_Distance(User.geom, pt)). \ 
     filter(func.ST_DWith(User.geom, pt, 1000).count() 

    if total_count > 0: 
     result_list = db.session.query(User, func_ST_Distance(User.geom, pt)). \ 
      filter(func.ST_DWithin(User.geom, pt, 1000).all() 

     return jsonify({'total_count': total_count, 'result_list':result_list}) 
    else 
     return jsonify({'total_count': total_count}) 

Es funktioniert tatsächlich, aber ich habe die gleichen Abfrageanweisungen bemerkt wird zweimal ausgeführt werden, wenn TOTAL_COUNT und result_list abfragt.

  1. Wie die wiederholte Abfrage Problem in TOTAL_COUNT und result_list optimieren?
  2. Wenn die Benutzertabelle Tausende von Zeilen enthält, vergleicht die Abfrage jede Zeile in der Benutzertabelle mit dem gegebenen Punkt? Wenn ja, wäre das eine langsame Leistung, wie löse ich das?

jeder Rat würde uns freuen!

Danke!

Antwort

0

Ich habe nie Flask-SQLAlchemy verwendet, aber was Sie wollen, ist ST_DWithin, die optimiert ist, um Geometrien innerhalb einer Entfernung zu finden, und kann GiST-Indizes verwenden. Dies ist besser als das Finden der Abstände zu Geometrien mit ST_Distance.

Wie es scheint, Sie haben SRID = 4326, würden Sie entweder geography Typen verwenden müssen metrische Abstand Ergebnisse zu erhalten, oder geometry zu dieser Art werfen können:

SELECT COUNT(*) 
FROM user 
WHERE ST_DWithin(user.geom::geography, 'SRID=4326;POINT(-122.4 37.7)'::geography, 1000.0); 

Sie einen räumlichen Index auf, dass schaffen mit etwas wie gegossen:

CREATE INDEX user_geog_idx ON user USING gist ((geom::geography)); 
+0

Danke Mike, ich werde es versuchen. :) – Raindrop