In my web app, I am using psycopg2 to query a postgreSQL database that holds thousands of location points. Let's say they can be categorized as offices and schools.
There are about 5500 offices and 550 schools. Fetching all of the results at once overloads it and causes my query to be cancelled. Therefore, I want to display only about 100 results, based on the part of the map the user is currently viewing.
My map's default view is of the United States. I want the database to only get 100 results each (100 offices and 100 schools) at any given time. If a user were to zoom in, it would be more detailed--different markers would appear.
This is what I have so far:
@app.route('/_ajax', methods= ['GET'])
def points():
myConnection = psycopg2.connect(host=hostname, user=username,
password=password, dbname=database)
cur = myConnection.cursor()
bounds = request.args.get('bounds')
officeID = []
office_info = []
cur.execute("""SELECT DISTINCT(o.office_id) from db_office o
WHERE o.location && ST_MakeEnvelope(left, bottom, right, top, 4326)
GROUP BY o.office_id LIMIT 100""")
for row in cur:
officeID.append(row[0])
for o in officeID:
cur.execute("""SELECT ST_Y(o.location::geometry),
ST_X(o.location::geometry),
o.owner, o.office_name from db_office o""".format(o))
for row in cur:
office_info.append([row[0], row[1], row[2], row[3]])
offices = dict(zip(officeID, office_info))
schoolID = []
school_info = []
cur.execute("""SELECT DISTINCT(s.school_id) from db_school s
WHERE s.location && ST_MakeEnvelope(left, bottom, right, top, 4326)
GROUP BY s.school_id LIMIT 100""")
for row in cur:
schoolID.append(row[0])
for s in schoolID:
cur.execute("""SELECT ST_Y(s.location::geometry),
ST_X(s.location::geometry),
s.owner, s.school_name from db_school s""".format(s))
for row in cur:
school_info.append([row[0], row[1], row[2], row[3]])
schools = dict(zip(schoolID, school_info))
return jsonify(offices=offices, schools=schools)
My AJAX call, which plots the markers, looks like this:
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
$(function() {
$.getJSON($SCRIPT_ROOT + '/_ajax?bounds=' + map.getBounds().toUrlValue(),
function(data) {
var places = [];
var marker;
Object.keys(data.offices).forEach(function(key) {
var offices = data.offices[key];
places.push(new google.maps.LatLng(offices[0], offices[1]))
marker = new google.maps.Marker({
position: {lat: offices[0], lng: offices[1]},
map: map
});
});
Object.keys(data.schools).forEach(function(key) {
var schools = data.schools[key];
places.push(new google.maps.LatLng(schools[0], schools[1]))
marker = new google.maps.Marker({
position: {lat: schools[0], lng: schools[1]},
map: map,
});
});
});
To summarize, this code fetches 100 of the offices and 100 of the schools and puts it into a dictionary, where the ids are the keys and the values are the information like latitude and longitude, etc.
This works and shows 100 results each but is not dependent on user location. How do change the results fetched by the database based on the user's view of the map?