diff --git a/app/src/search.js b/app/src/search.js new file mode 100644 index 00000000..14f2ab1a --- /dev/null +++ b/app/src/search.js @@ -0,0 +1,31 @@ +/** + * Search table access + * - to support navigation around the map + * - some separation from building attributes - here we might use other points of interest + * or cues to broadly locate the user (postcode, borough name...) + * - this DOES expose geometry, another reason to keep this clearly separated from building + * data + */ +import db from './db'; + +function queryLocation(term){ + const max_results = 5; + return db.manyOrNone( + `SELECT + search_str, search_class, ST_AsGeoJSON(center), zoom, + search_str <-> $1 AS dist + FROM + search_locations + ORDER BY + dist + LIMIT $2;`, + [term, max_results] + ).catch((error) => { + console.error(error); + return undefined; + }); +} + +export { + queryLocation +}; diff --git a/app/src/server.js b/app/src/server.js index 6f9cd7ed..51e1a250 100644 --- a/app/src/server.js +++ b/app/src/server.js @@ -27,6 +27,7 @@ import { likeBuilding, unlikeBuilding } from './building'; +import { searchLocation, queryLocation } from './search'; import tileserver from './tileserver'; import { parseBuildingURL } from './parse'; @@ -393,4 +394,39 @@ server.post('/api/key', function(req, res){ }); }) +// GET search +server.get('/search', function(req, res){ + const search_term = req.query.q; + if (!search_term){ + res.send({ + error: 'Please provide a search term' + }) + return + } + queryLocation(search_term).then((results) => { + if (typeof(results) === "undefined") { + res.send({ + error: 'Database error' + }) + return + } + res.send({ + results: results.map(item => { + // map from DB results to GeoJSON Feature objects + const geom = JSON.parse(item.st_asgeojson) + return { + type: 'Feature', + attributes: { + label: item.search_str, + zoom: item.zoom || 9 + }, + geometry: geom + } + }) + }) + }).catch(function(error){ + res.send(error); + }); +}) + export default server;