Optimize search performance

Huge speedup for searching

Prior to these changes, the search logic created many database queries for each result.
The search controller would loop over all the OTUs for selected taxa, and query the database for trait criteria on each one.  This resulted in an additional query for every OTU.  On top of that, the OTU names were implemented in a way that caused several more queries to the database for every row.  Similar issues plagued the fetching of sources, notes, and metadata

Now, instead of looping over OTUs, we loop over ContinuousTraitValues and CategoricalTraitValues, leveraging the ActiveRelation where() function  to do the initial filtering.

Additionally, the includes() function is used to pre-fetch from related tables (source_references, notes) to avoid single-row select statements inside the loop

Prior to these optimizations, a sample search (all data from vertebrates dataset) would take about 80s to complete (on traitdb-dev).  After the optimizations, this search completes in 2s (on local macbook)

This changeset also includes some minor display tweaks to OTU names on the search page