Skip to content

Commit

Permalink
add observation search obscuration parameter #472
Browse files Browse the repository at this point in the history
  • Loading branch information
pleary committed Nov 12, 2024
1 parent c1c5191 commit 6123ffd
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 0 deletions.
56 changes: 56 additions & 0 deletions lib/models/observation_query_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,62 @@ ObservationQueryBuilder.reqToElasticQueryComponents = async req => {
} );
}

if ( params.obscuration ) {
let queryObscurationTypes;
let obscurationFilters;
const requestedObscuration = util.paramArray( params.obscuration );
if ( _.includes( requestedObscuration, "obscured" )
&& _.includes( requestedObscuration, "private" ) ) {
queryObscurationTypes = ["obscured", "private"];
} else if ( _.includes( requestedObscuration, "obscured" ) ) {
queryObscurationTypes = ["obscured"];
} else if ( _.includes( requestedObscuration, "private" ) ) {
queryObscurationTypes = ["private"];
}
if ( !_.isEmpty( queryObscurationTypes ) ) {
obscurationFilters = [
esClient.termFilter( "geoprivacy", queryObscurationTypes ),
esClient.termFilter( "taxon_geoprivacy", queryObscurationTypes )
];
}
let obscurationNoneFilter;
if ( _.includes( requestedObscuration, "none" ) ) {
obscurationNoneFilter = {
bool: {
filter: [{
bool: {
should: [
esClient.termFilter( "geoprivacy", "open" ),
{ bool: { must_not: { exists: { field: "geoprivacy" } } } }
]
}
}, {
bool: {
should: [
esClient.termFilter( "taxon_geoprivacy", "open" ),
{ bool: { must_not: { exists: { field: "taxon_geoprivacy" } } } }
]
}
}]
}
};
}
// if only `none` is requested, the obscurationNoneFilter can be added without `should`
if ( obscurationNoneFilter && _.isEmpty( obscurationFilters ) ) {
searchFilters.push( obscurationNoneFilter );
} else if ( !_.isEmpty( obscurationFilters ) ) {
// if any other values are requested, use a `should` filter. Add the none option if set
if ( !_.isEmpty( obscurationNoneFilter ) ) {
obscurationFilters.push( obscurationNoneFilter );
}
searchFilters.push( {
bool: {
should: obscurationFilters
}
} );
}
}

_.each( ["geoprivacy", "taxon_geoprivacy"], geoprivacyField => {
const geoprivacyFieldFilters = [];
_.each( util.paramArray( params[geoprivacyField] ), paramValue => {
Expand Down
1 change: 1 addition & 0 deletions lib/views/_observation_search_params_v1.yml.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
- $ref: "#/parameters/csi"
- $ref: "#/parameters/geoprivacy"
- $ref: "#/parameters/taxon_geoprivacy"
- $ref: "#/parameters/obscuration"
- $ref: "#/parameters/hrank"
- $ref: "#/parameters/lrank"
- $ref: "#/parameters/iconic_taxa"
Expand Down
12 changes: 12 additions & 0 deletions lib/views/swagger_v1.yml.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -2624,6 +2624,18 @@ parameters:
- obscured_private
- open
- private
obscuration:
name: obscuration
type: array
items:
type: string
in: query
description: |
Must have `geoprivacy` or `taxon_geoprivacy` fields matching these values
enum:
- obscured
- private
- none
hrank:
name: hrank
type: string
Expand Down
5 changes: 5 additions & 0 deletions openapi/schema/request/observations_search.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ module.exports = Joi.object( ).keys( {
"open",
"private"
) ),
obscuration: Joi.array( ).items( Joi.string( ).valid(
"obscured",
"private",
"none"
) ).description( "Filter by observations where the `geoprivacy` or `taxon_geoprivacy` match these values" ),
hrank: Joi.array( ).items( Joi.string( ).valid(
"kingdom",
"phylum",
Expand Down
10 changes: 10 additions & 0 deletions schema/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,16 @@
"private_geojson": { "type": "Point", "coordinates": [ 4, 3 ] },
"place_guess": "Tangerina",
"captive": true
},
{
"id": 2024111201,
"uuid": "2450abff-8007-46a8-ae88-45808f5dc83a ",
"user": {
"id": 123,
"login": "a-user",
"name": "A User"
},
"taxon_geoprivacy": "private"
}
]
},
Expand Down
70 changes: 70 additions & 0 deletions test/integration/v2/observations.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,76 @@ describe( "Observations", ( ) => {
} ).expect( "Content-Type", /json/ )
.expect( 200, done );
} );

describe( "obscuration", ( ) => {
it( "filters by obscuration=obscured", function ( done ) {
request( this.app ).get(
"/v2/observations?obscuration=obscured&fields=geoprivacy,taxon_geoprivacy"
).expect( res => {
expect( res.body.results.length ).to.above( 0 );
expect( _.every( res.body.results, r => (
r.geoprivacy === "obscured" || r.taxon_geoprivacy === "obscured"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy === "obscured" && r.taxon_geoprivacy !== "obscured"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy !== "obscured" && r.taxon_geoprivacy === "obscured"
) ) ).to.be.true;
} ).expect( "Content-Type", /json/ )
.expect( 200, done );
} );

it( "filters by obscuration=private", function ( done ) {
request( this.app ).get(
"/v2/observations?per_page=200&obscuration=private&fields=geoprivacy,taxon_geoprivacy"
).expect( res => {
expect( res.body.results.length ).to.above( 0 );
expect( _.every( res.body.results, r => (
r.geoprivacy === "private" || r.taxon_geoprivacy === "private"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy === "private" && r.taxon_geoprivacy !== "private"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy !== "private" && r.taxon_geoprivacy === "private"
) ) ).to.be.true;
} ).expect( "Content-Type", /json/ )
.expect( 200, done );
} );

it( "filters by obscuration=obscured,private", function ( done ) {
request( this.app ).get(
"/v2/observations?per_page=200&obscuration=obscured,private&fields=geoprivacy,taxon_geoprivacy"
).expect( res => {
expect( res.body.results.length ).to.above( 0 );
expect( _.every( res.body.results, r => (
r.geoprivacy === "private" || r.taxon_geoprivacy === "private"
|| r.geoprivacy === "obscured" || r.taxon_geoprivacy === "obscured"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy !== "obscured" && r.taxon_geoprivacy !== "obscured"
) ) ).to.be.true;
expect( _.some( res.body.results, r => (
r.geoprivacy !== "private" && r.taxon_geoprivacy !== "private"
) ) ).to.be.true;
} ).expect( "Content-Type", /json/ )
.expect( 200, done );
} );

it( "filters by obscuration=none", function ( done ) {
request( this.app ).get(
"/v2/observations?per_page=200&obscuration=none&fields=geoprivacy,taxon_geoprivacy"
).expect( res => {
expect( res.body.results.length ).to.above( 0 );
expect( _.every( res.body.results, r => (
r.geoprivacy !== "private" && r.taxon_geoprivacy !== "private"
&& r.geoprivacy !== "obscured" && r.taxon_geoprivacy !== "obscured"
) ) ).to.be.true;
} ).expect( "Content-Type", /json/ )
.expect( 200, done );
} );
} );
} );

describe( "create", ( ) => {
Expand Down

0 comments on commit 6123ffd

Please sign in to comment.