Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions lib/controllers/v2/exemplar_identifications_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,21 @@ const ExemplarIdentificationsController = class ExemplarIdentificationsControlle

if ( params.q ) {
searchFilters.push( {
match: {
"identification.body": {
query: params.q,
operator: "and"
}
bool: {
should: [{
match: {
"identification.body": {
query: params.q,
operator: "and"
}
}
}, {
match: {
"identification.user.login_autocomplete": {
query: params.q
}
}
}]
}
} );
}
Expand Down
27 changes: 22 additions & 5 deletions schema/database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2781,7 +2781,9 @@ CREATE TABLE public.moderator_actions (
resource_user_id integer,
resource_parent_id integer,
resource_parent_type character varying,
resource_content text
resource_content text,
suspended_until timestamp without time zone,
last_edited_by_user_id integer
);


Expand Down Expand Up @@ -6118,7 +6120,8 @@ CREATE TABLE public.users (
virtuous_donor_contact_id integer,
fundraiseup_plan_frequency character varying,
fundraiseup_plan_status character varying,
fundraiseup_plan_started_at date
fundraiseup_plan_started_at date,
suspended_until timestamp without time zone
);


Expand Down Expand Up @@ -9181,7 +9184,7 @@ CREATE INDEX index_custom_projects_on_project_id ON public.custom_projects USING
-- Name: index_delayed_jobs_on_unique_hash; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_delayed_jobs_on_unique_hash ON public.delayed_jobs USING btree (unique_hash);
CREATE UNIQUE INDEX index_delayed_jobs_on_unique_hash ON public.delayed_jobs USING btree (unique_hash);


--
Expand Down Expand Up @@ -11365,7 +11368,7 @@ CREATE INDEX index_users_on_curator_sponsor_id ON public.users USING btree (cura
-- Name: index_users_on_email; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_users_on_email ON public.users USING btree (email);
CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);


--
Expand Down Expand Up @@ -11473,6 +11476,13 @@ CREATE INDEX index_users_on_spammer ON public.users USING btree (spammer);
CREATE INDEX index_users_on_state ON public.users USING btree (state);


--
-- Name: index_users_on_suspended_until; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_users_on_suspended_until ON public.users USING btree (suspended_until);


--
-- Name: index_users_on_unconfirmed_email; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -12180,6 +12190,13 @@ INSERT INTO "schema_migrations" (version) VALUES
('20251119043443'),
('20251119130558'),
('20251202224705'),
('20260119093529');
('20260119093529'),
('20260319212735'),
('20260326000001'),
('20260326000002'),
('20260406164708'),
('20260511210120'),
('20260514211433'),
('20260514215925');


10 changes: 10 additions & 0 deletions schema/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@
},
"observation": {
"id": 1
},
"user": {
"id": 121,
"login": "user121",
"login_autocomplete": "user121"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to add the login_exact field to these two fixtures as well?

Suggested change
"login_autocomplete": "user121"
"login_autocomplete": "user121",
"login_exact": "user121"

}
}
},
Expand All @@ -188,6 +193,11 @@
},
"observation": {
"id": 1
},
"user": {
"id": 122,
"login": "user122",
"login_autocomplete": "user122"
}
}
},
Expand Down
12 changes: 12 additions & 0 deletions schema/indices/exemplar_identifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@
"type": "keyword"
}
}
},
"login": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how login and login_exact are being used, since we only match on login_autocomplete in the controller. Are these just different matchers that we provide access to for all strings that should be queryable for future use cases?

"type": "text",
"analyzer": "ascii_snowball_analyzer"
},
"login_autocomplete": {
"type": "text",
"analyzer": "autocomplete_analyzer",
"search_analyzer": "standard_analyzer"
},
"login_exact": {
"type": "keyword"
}
}
},
Expand Down
69 changes: 56 additions & 13 deletions test/integration/v2/exemplar_identifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,6 @@ describe( "ExemplarIdentifications", ( ) => {
.expect( 200, done );
} );

it( "can filter by query", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=7&q=unnominated&fields=all" )
.set( "Authorization", adminToken )
.set( "Content-Type", "application/json" )
.expect( "Content-Type", /json/ )
.expect( res => {
expect( res.body.total_results ).to.eq( 1 );
expect( res.body.results.length ).to.eq( 1 );
expect( res.body.results[0].identification.body ).to.eq( "taxon 7 unnominated" );
} )
.expect( 200, done );
} );

it( "can filter by term_value_id", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=3&term_value_id=2&fields=all" )
.set( "Authorization", adminToken )
Expand All @@ -172,5 +159,61 @@ describe( "ExemplarIdentifications", ( ) => {
} )
.expect( 200, done );
} );

describe( "q", ( ) => {
it( "can filter by query", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=7&q=unnominated&fields=all" )
.set( "Authorization", adminToken )
.set( "Content-Type", "application/json" )
.expect( "Content-Type", /json/ )
.expect( res => {
expect( res.body.total_results ).to.eq( 1 );
expect( res.body.results.length ).to.eq( 1 );
expect( res.body.results[0].identification.body ).to.eq( "taxon 7 unnominated" );
} )
.expect( 200, done );
} );

it( "can filter by user login", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=7&q=user121&fields=all" )
.set( "Authorization", adminToken )
.set( "Content-Type", "application/json" )
.expect( "Content-Type", /json/ )
.expect( res => {
expect( res.body.total_results ).to.eq( 1 );
expect( res.body.results.length ).to.eq( 1 );
expect( res.body.results[0].identification.user.login ).to.eq( "user121" );
} )
.expect( 200, done );
} );

it( "can filter by query and user login", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=7&q=unnominated user121&fields=all" )
.set( "Authorization", adminToken )
.set( "Content-Type", "application/json" )
.expect( "Content-Type", /json/ )
.expect( res => {
expect( res.body.total_results ).to.eq( 1 );
expect( res.body.results.length ).to.eq( 1 );
expect( res.body.results[0].identification.user.login ).to.eq( "user121" );
} )
.expect( 200, done );
} );

it( "can filter by partial query and user login", function ( done ) {
request( this.app ).get( "/v2/exemplar_identifications?direct_taxon_id=7&q=nom user12&fields=all" )
.set( "Authorization", adminToken )
.set( "Content-Type", "application/json" )
.expect( "Content-Type", /json/ )
.expect( res => {
expect( res.body.total_results ).to.eq( 2 );
expect( res.body.results.length ).to.eq( 2 );
res.body.results.forEach( result => {
expect( result.identification.user.login ).to.be.oneOf( ["user121", "user122"] );
} );
} )
.expect( 200, done );
} );
} );
} );
} );
Loading