@@ -879,6 +879,104 @@ module.exports = async function ({ plants, nurseries }) {
879879 }
880880 }
881881 }
882+ // Calculate min/max height from filtered plants (excluding height filter)
883+ let heightRange = { min : 0 , max : 0 } ;
884+ if ( ! req . query . favorites ) {
885+ const heightFilter = filters . find ( f => f . name === "Height (feet)" ) ;
886+ if ( heightFilter && heightFilter . range ) {
887+ // Rebuild all filter conditions from req.query, excluding height filter
888+ // This ensures we include ALL user filters (States, Sun Exposure, etc.)
889+ const heightMatchAnd = [ ] ;
890+ for ( const filter of filters ) {
891+ // Skip the height filter itself
892+ if ( filter . name === "Height (feet)" ) {
893+ continue ;
894+ }
895+
896+ if ( filter . range ) {
897+ const min = parseInt ( req . query ?. [ filter . name ] ?. min ) ;
898+ const max = parseInt ( req . query ?. [ filter . name ] ?. max ) ;
899+ if (
900+ ! isNaN ( min ) &&
901+ ! isNaN ( max ) &&
902+ min <= max &&
903+ ( min !== 0 || max !== filter . choices . length - 1 )
904+ ) {
905+ const $in = [ ] ;
906+ for ( let i = min ; i <= max ; i ++ ) {
907+ $in . push ( i ) ;
908+ }
909+ if ( $in . length ) {
910+ heightMatchAnd . push ( {
911+ [ filter . byNumber ] : {
912+ $in,
913+ } ,
914+ } ) ;
915+ }
916+ }
917+ } else if ( filter . boolean ) {
918+ let input = req . query [ filter . name ] || [ ] ;
919+ if ( input && input . length ) {
920+ heightMatchAnd . push ( {
921+ [ filter . name ] : true ,
922+ } ) ;
923+ }
924+ } else if ( filter . array ) {
925+ let input = req . query [ filter . name ] || [ ] ;
926+ if ( ! Array . isArray ( input ) ) {
927+ input = [ input ] ;
928+ }
929+ if ( input && input . length ) {
930+ heightMatchAnd . push ( {
931+ [ filter . name ] : {
932+ $in : input ,
933+ } ,
934+ } ) ;
935+ }
936+ }
937+ }
938+
939+ // Build match query with all filters except height
940+ const matchQuery = { } ;
941+ if ( heightMatchAnd . length > 0 ) {
942+ matchQuery . $and = heightMatchAnd ;
943+ }
944+
945+ // For semantic search, use scoredResults if available
946+ if ( query . _useSemantic && scoredResults ) {
947+ const allHeights = [ ] ;
948+ for ( const plant of scoredResults ) {
949+ const heights = plant [ "Height (feet) By Number" ] ;
950+ if ( Array . isArray ( heights ) && heights . length > 0 ) {
951+ allHeights . push ( ...heights ) ;
952+ }
953+ }
954+ if ( allHeights . length > 0 ) {
955+ heightRange . min = Math . min ( ...allHeights ) ;
956+ heightRange . max = Math . max ( ...allHeights ) ;
957+ }
958+ } else {
959+ // Use aggregation to find min/max from filtered plants
960+ const heightAggregation = await plants . aggregate ( [
961+ { $match : matchQuery } ,
962+ { $unwind : { path : `$${ heightFilter . byNumber } ` , preserveNullAndEmptyArrays : false } } ,
963+ {
964+ $group : {
965+ _id : null ,
966+ minHeight : { $min : `$${ heightFilter . byNumber } ` } ,
967+ maxHeight : { $max : `$${ heightFilter . byNumber } ` }
968+ }
969+ }
970+ ] ) . toArray ( ) ;
971+
972+ if ( heightAggregation . length > 0 && heightAggregation [ 0 ] . minHeight !== null ) {
973+ heightRange . min = heightAggregation [ 0 ] . minHeight ;
974+ heightRange . max = heightAggregation [ 0 ] . maxHeight ;
975+ }
976+ }
977+ }
978+ }
979+
882980 let response = {
883981 results,
884982 total,
@@ -898,6 +996,7 @@ module.exports = async function ({ plants, nurseries }) {
898996 ) ,
899997 ] )
900998 ) ,
999+ heightRange : heightRange ,
9011000 } ;
9021001 }
9031002 for ( const filter of filters ) {
0 commit comments