diff --git a/lib/controllers/v1/computervision_controller.js b/lib/controllers/v1/computervision_controller.js index cc5b5ac7..d5fd026e 100644 --- a/lib/controllers/v1/computervision_controller.js +++ b/lib/controllers/v1/computervision_controller.js @@ -619,6 +619,10 @@ const ComputervisionController = class ComputervisionController { } static async languageSearch( req ) { + if ( !req.userSession || !req.userSession.isAdmin ) { + throw util.httpError( 401, "Unauthorized" ); + } + if ( _.isEmpty( req.query.q ) ) { throw util.httpError( 422, "Missing required parameter `q`" ); } @@ -656,21 +660,22 @@ const ComputervisionController = class ComputervisionController { const photos = _.keyBy( json.results, "photo_id" ); const photosQuery = squel .select( ) - .field( "p.id photo_id, MAX(o.id) observation_id" ) - .from( "photos p" ) - .join( "observation_photos op", null, "p.id = op.photo_id" ) - .join( "observations o", null, "op.observation_id = o.id" ) - .where( "p.id IN ?", _.keys( photos ) ) - .group( "p.id" ); + .field( "op.photo_id, op.observation_id" ) + .from( "observation_photos op" ) + .where( "op.photo_id IN ?", _.keys( photos ) ); const { rows } = await pgClient.replica.query( photosQuery.toString( ) ); - const results = []; - _.each( rows, row => { - results.push( { + const resultsObject = { }; + _.each( _.reverse( _.sortBy( rows, "observation_id" ) ), row => { + if ( _.has( resultsObject, row.photo_id ) ) { + return; + } + resultsObject[row.photo_id] = { observation_id: row.observation_id, photo_id: row.photo_id, score: photos[row.photo_id] - } ); + }; } ); + const results = _.values( resultsObject ); const localeOpts = util.localeOpts( req ); await Observation.preloadInto( req, results, localeOpts ); _.each( results, r => { @@ -681,7 +686,7 @@ const ComputervisionController = class ComputervisionController { total_results: _.size( results ), page: Number( req.query.page ) || 1, per_page: _.size( results ), - results + results: _.reverse( _.sortBy( results, "score" ) ) }; return response; }