From 5c7e62e8002d4bd34ac77eee5a5fed7f2b581518 Mon Sep 17 00:00:00 2001 From: Patrick Leary Date: Tue, 30 Jul 2024 11:58:26 -0400 Subject: [PATCH] can lookup projects by slug_keyword #250 --- lib/controllers/v1/projects_controller.js | 4 +++- lib/controllers/v1/taxa_controller.js | 1 + lib/models/es_model.js | 8 ++++++-- openapi/schema/response/conservation_status.js | 1 + schema/fixtures.js | 10 +++++++++- schema/indices/projects.js | 3 +++ test/integration/v1/observations.js | 15 +++++++++++++++ test/integration/v1/projects.js | 8 ++++++++ 8 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lib/controllers/v1/projects_controller.js b/lib/controllers/v1/projects_controller.js index 861dc081..f716ca4d 100644 --- a/lib/controllers/v1/projects_controller.js +++ b/lib/controllers/v1/projects_controller.js @@ -20,6 +20,7 @@ const ProjectsController = class ProjectsController { bool: { should: [ { term: { slug: req.query.q } }, + { term: { slug_keyword: req.query.q } }, { match: { title_autocomplete: { query: req.query.q, operator: "and" } } }, { match: { title: { query: req.query.q, operator: "and" } } } ] @@ -233,7 +234,8 @@ const ProjectsController = class ProjectsController { bool: { should: [ { terms: { id: numericIDs } }, - { terms: { slug: ids } } + { terms: { slug: ids } }, + { terms: { slug_keyword: ids } } ] } }, diff --git a/lib/controllers/v1/taxa_controller.js b/lib/controllers/v1/taxa_controller.js index 5e8568d8..ea90ffb2 100644 --- a/lib/controllers/v1/taxa_controller.js +++ b/lib/controllers/v1/taxa_controller.js @@ -1218,6 +1218,7 @@ TaxaController.suggest = async req => { if ( response.queryTaxon ) { response.queryTaxon = new Taxon( response.queryTaxon ); response.queryTaxon.prepareForResponse( localeOpts ); + await TaxaController.assignPlaces( [response.queryTaxon] ); } } if ( req.suggestParams.place_id ) { diff --git a/lib/models/es_model.js b/lib/models/es_model.js index 26a968b8..aac18d63 100644 --- a/lib/models/es_model.js +++ b/lib/models/es_model.js @@ -18,11 +18,15 @@ const ESModel = class ESModel { if ( options.searchSlug ) { const numericIDs = _.filter( ids, id => Number( id ) ); if ( _.isEmpty( numericIDs ) ) { - optionsFilters.push( { terms: { slug: ids } } ); + should = [ + { terms: { slug: ids } }, + { terms: { slug_keyword: ids } } + ]; } else { should = [ { terms: { id: numericIDs } }, - { terms: { slug: ids } } + { terms: { slug: ids } }, + { terms: { slug_keyword: ids } } ]; } } else { diff --git a/openapi/schema/response/conservation_status.js b/openapi/schema/response/conservation_status.js index 9ad87849..9d4cdfbf 100644 --- a/openapi/schema/response/conservation_status.js +++ b/openapi/schema/response/conservation_status.js @@ -15,6 +15,7 @@ module.exports = Joi.object( ).keys( { status: Joi.string( ), status_name: Joi.string( ), taxon_id: Joi.number( ).integer( ), + user_id: Joi.number( ).integer( ).valid( null ), url: Joi.string( ).valid( null ) } ).unknown( false ).meta( { className: "ConservationStatus" } ) .valid( null ); diff --git a/schema/fixtures.js b/schema/fixtures.js index ebaf85c1..23bf7013 100644 --- a/schema/fixtures.js +++ b/schema/fixtures.js @@ -526,7 +526,7 @@ "min_species_ancestry": "1,2,3,4,5", "rank_level": 10 }, - "project_ids": [ 543 ], + "project_ids": [ 543, 2024072601 ], "private_geojson": { "type": "Point", "coordinates": [ 2, 1 ] } }, { @@ -1359,6 +1359,14 @@ } ], "prefers_user_trust": false + }, + { + "id": 2024072601, + "title": "Proyecto águilas", + "title_autocomplete": "Proyecto águilas", + "title_exact": "Proyecto águilas", + "slug": "proyecto-águilas", + "slug_keyword": "proyecto-águilas" } ] }, diff --git a/schema/indices/projects.js b/schema/indices/projects.js index 7ba88f89..d5d7bb26 100644 --- a/schema/indices/projects.js +++ b/schema/indices/projects.js @@ -333,6 +333,9 @@ "analyzer": "keyword_analyzer", "type": "text" }, + "slug_keyword": { + "type": "keyword" + }, "spam": { "type": "boolean" }, diff --git a/test/integration/v1/observations.js b/test/integration/v1/observations.js index c1a3e142..4b2fc9ab 100644 --- a/test/integration/v1/observations.js +++ b/test/integration/v1/observations.js @@ -463,6 +463,21 @@ describe( "Observations", ( ) => { .expect( 422, done ); } ); + it( "raises an error for missing projects", function ( done ) { + request( this.app ).get( "/v1/observations?project_id=nonsense" ) + .expect( res => { + expect( res.error.text ).to.eq( "{\"error\":\"Unknown project_id: [nonsense]\",\"status\":422}" ); + } ).expect( "Content-Type", /json/ ) + .expect( 422, done ); + } ); + + it( "looks up projects with non-ASCII characters", function ( done ) { + request( this.app ).get( "/v1/observations?project_id=proyecto-águilas" ) + .expect( res => { + expect( res.body.total_results ).to.eq( 1 ); + } ).expect( 200, done ); + } ); + it( "return iconic taxon names", function ( done ) { request( this.app ).get( "/v1/observations?id=1" ) .expect( res => { diff --git a/test/integration/v1/projects.js b/test/integration/v1/projects.js index c6c557c1..984dc8da 100644 --- a/test/integration/v1/projects.js +++ b/test/integration/v1/projects.js @@ -117,6 +117,14 @@ describe( "Projects", ( ) => { .expect( 200, done ); } ); + it( "returns projects by slug with non-ASCII characters", function ( done ) { + request( this.app ).get( "/v1/projects/proyecto-águilas" ) + .expect( res => { + expect( res.body.results[0].slug ).to.eq( "proyecto-águilas" ); + } ).expect( "Content-Type", /json/ ) + .expect( 200, done ); + } ); + it( "returns an error if too many IDs are requested", function ( done ) { const ids = []; const count = 101;