@@ -176,51 +176,45 @@ module.exports = async function ({ plants, nurseries }) {
176176 const queryRegex = new RegExp ( queryLower , 'i' ) ;
177177 const sections = [ ] ;
178178
179- // Search Plants by Common Name and Scientific Name
180- const plantsByCommonName = await plants . find ( {
181- "Common Name" : queryRegex
182- } )
183- . sort ( { "Recommendation Score" : - 1 } )
184- . limit ( 10 )
185- . toArray ( ) ;
186-
187- const plantsByScientificName = await plants . find ( {
188- "Scientific Name" : queryRegex
189- } )
190- . sort ( { "Recommendation Score" : - 1 } )
191- . limit ( 10 )
192- . toArray ( ) ;
179+ // Search Genus
180+ const genusValues = await plants . distinct ( "Genus" ) ;
181+ const matchingGenus = genusValues
182+ . filter ( value => value && queryRegex . test ( value ) )
183+ . slice ( 0 , 10 ) ;
193184
194- // Combine and deduplicate plant results
195- const plantMap = new Map ( ) ;
196- plantsByCommonName . forEach ( plant => {
197- plantMap . set ( plant . _id , {
198- plantId : plant . _id ,
199- commonName : plant [ "Common Name" ] ,
200- scientificName : plant [ "Scientific Name" ] ,
201- displayText : plant [ "Common Name" ] ,
202- subtitle : plant [ "Scientific Name" ] ,
203- action : "navigateToPlant"
185+ if ( matchingGenus . length > 0 ) {
186+ sections . push ( {
187+ type : "filter" ,
188+ filterName : "Genus" ,
189+ label : "Genus" ,
190+ items : matchingGenus . map ( value => ( {
191+ value : value ,
192+ displayText : value ,
193+ action : "applyFilter" ,
194+ filterName : "Genus" ,
195+ filterValue : value
196+ } ) )
204197 } ) ;
205- } ) ;
206- plantsByScientificName . forEach ( plant => {
207- if ( ! plantMap . has ( plant . _id ) ) {
208- plantMap . set ( plant . _id , {
209- plantId : plant . _id ,
210- commonName : plant [ "Common Name" ] ,
211- scientificName : plant [ "Scientific Name" ] ,
212- displayText : plant [ "Common Name" ] ,
213- subtitle : plant [ "Scientific Name" ] ,
214- action : "navigateToPlant"
215- } ) ;
216- }
217- } ) ;
198+ }
218199
219- if ( plantMap . size > 0 ) {
200+ // Search Family
201+ const familyValues = await plants . distinct ( "Family" ) ;
202+ const matchingFamily = familyValues
203+ . filter ( value => value && queryRegex . test ( value ) )
204+ . slice ( 0 , 10 ) ;
205+
206+ if ( matchingFamily . length > 0 ) {
220207 sections . push ( {
221- type : "plant" ,
222- label : "Plant" ,
223- items : Array . from ( plantMap . values ( ) )
208+ type : "filter" ,
209+ filterName : "Family" ,
210+ label : "Family" ,
211+ items : matchingFamily . map ( value => ( {
212+ value : value ,
213+ displayText : value ,
214+ action : "applyFilter" ,
215+ filterName : "Family" ,
216+ filterValue : value
217+ } ) )
224218 } ) ;
225219 }
226220
@@ -268,6 +262,54 @@ module.exports = async function ({ plants, nurseries }) {
268262 } ) ;
269263 }
270264
265+ // Search Plants by Common Name and Scientific Name (kept last so filters are shown first)
266+ const plantsByCommonName = await plants . find ( {
267+ "Common Name" : queryRegex
268+ } )
269+ . sort ( { "Recommendation Score" : - 1 } )
270+ . limit ( 10 )
271+ . toArray ( ) ;
272+
273+ const plantsByScientificName = await plants . find ( {
274+ "Scientific Name" : queryRegex
275+ } )
276+ . sort ( { "Recommendation Score" : - 1 } )
277+ . limit ( 10 )
278+ . toArray ( ) ;
279+
280+ // Combine and deduplicate plant results
281+ const plantMap = new Map ( ) ;
282+ plantsByCommonName . forEach ( plant => {
283+ plantMap . set ( plant . _id , {
284+ plantId : plant . _id ,
285+ commonName : plant [ "Common Name" ] ,
286+ scientificName : plant [ "Scientific Name" ] ,
287+ displayText : plant [ "Common Name" ] ,
288+ subtitle : plant [ "Scientific Name" ] ,
289+ action : "navigateToPlant"
290+ } ) ;
291+ } ) ;
292+ plantsByScientificName . forEach ( plant => {
293+ if ( ! plantMap . has ( plant . _id ) ) {
294+ plantMap . set ( plant . _id , {
295+ plantId : plant . _id ,
296+ commonName : plant [ "Common Name" ] ,
297+ scientificName : plant [ "Scientific Name" ] ,
298+ displayText : plant [ "Common Name" ] ,
299+ subtitle : plant [ "Scientific Name" ] ,
300+ action : "navigateToPlant"
301+ } ) ;
302+ }
303+ } ) ;
304+
305+ if ( plantMap . size > 0 ) {
306+ sections . push ( {
307+ type : "plant" ,
308+ label : "Plant" ,
309+ items : Array . from ( plantMap . values ( ) )
310+ } ) ;
311+ }
312+
271313 res . json ( { query, sections } ) ;
272314 } catch ( error ) {
273315 console . error ( "Autocomplete error:" , error ) ;
@@ -446,6 +488,18 @@ module.exports = async function ({ plants, nurseries }) {
446488 value : [ ] ,
447489 array : true ,
448490 } ,
491+ {
492+ name : "Genus" ,
493+ value : [ ] ,
494+ array : true ,
495+ unwind : false ,
496+ } ,
497+ {
498+ name : "Family" ,
499+ value : [ ] ,
500+ array : true ,
501+ unwind : false ,
502+ } ,
449503 {
450504 name : "Sun Exposure Flags" ,
451505 value : [ ] ,
@@ -843,16 +897,20 @@ module.exports = async function ({ plants, nurseries }) {
843897 {
844898 $match : matchQuery ,
845899 } ,
846- {
900+ ] ;
901+ // Some "array" filters are represented as scalar strings in MongoDB (e.g. Genus/Family).
902+ // Only unwind when the field is actually an array.
903+ if ( filter . unwind !== false ) {
904+ aQuery . push ( {
847905 $unwind : `$${ filter . name } ` ,
906+ } ) ;
907+ }
908+ aQuery . push ( {
909+ $group : {
910+ _id : `$${ filter . name } ` ,
911+ count : { $sum : 1 } ,
848912 } ,
849- {
850- $group : {
851- _id : `$${ filter . name } ` ,
852- count : { $sum : 1 } ,
853- } ,
854- } ,
855- ] ;
913+ } ) ;
856914 filter . counts = await plants . aggregate ( aQuery ) . toArray ( ) ;
857915 } else if ( filter . boolean ) {
858916 const matchQuery = { ...query } ;
0 commit comments