@@ -826,11 +826,19 @@ async function searchSymbolsSingleTerm(
826826 WITH s, f,
827827 CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
828828 CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
829+ CASE
830+ WHEN lower(coalesce(s.searchText, '')) CONTAINS (' ' || lower($query) || ' ')
831+ OR lower(coalesce(s.searchText, '')) STARTS WITH (lower($query) || ' ')
832+ OR lower(coalesce(s.searchText, '')) ENDS WITH (' ' || lower($query))
833+ THEN 0 ELSE 1
834+ END AS wordBoundaryRank,
829835 CASE
830836 WHEN f.relPath CONTAINS '/adapter/' THEN 2
831837 WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
832838 WHEN f.relPath STARTS WITH 'scripts/' THEN 2
833839 WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
840+ WHEN f.relPath CONTAINS 'target/' THEN 2
841+ WHEN f.relPath CONTAINS 'vendor/' THEN 2
834842 ELSE 0
835843 END AS filePenalty,
836844 CASE s.kind
@@ -861,8 +869,9 @@ async function searchSymbolsSingleTerm(
861869 s.invariantsJson AS invariantsJson,
862870 s.sideEffectsJson AS sideEffectsJson,
863871 s.updatedAt AS updatedAt
864- ORDER BY exactNameRank, ciExactNameRank, filePenalty, kindRank, nameMatchRank` ,
865- { repoId, query : term } ,
872+ ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
873+ LIMIT $limit` ,
874+ { repoId, query : term , limit : 200 } ,
866875 ) ;
867876}
868877
@@ -923,7 +932,16 @@ export interface SearchSymbolLiteRow {
923932export function splitSearchTerms ( query : string ) : string [ ] {
924933 const trimmed = query . trim ( ) ;
925934 if ( ! trimmed ) return [ ] ;
926- if ( ! trimmed . includes ( " " ) ) return [ trimmed ] ;
935+ if ( ! trimmed . includes ( " " ) ) {
936+ // Split camelCase/PascalCase into words for multi-term search
937+ const words = trimmed . match (
938+ / [ A - Z ] { 2 , } (? = [ A - Z ] [ a - z ] | $ ) | [ A - Z ] ? [ a - z ] + | [ A - Z ] + | [ 0 - 9 ] + / g,
939+ ) ;
940+ if ( words && words . length > 1 ) {
941+ return words . map ( ( w ) => w . toLowerCase ( ) ) ;
942+ }
943+ return [ trimmed ] ;
944+ }
927945 return trimmed . split ( / \s + / ) . filter ( ( t ) => t . length > 0 ) ;
928946}
929947
@@ -941,11 +959,19 @@ async function searchSymbolsLiteSingleTerm(
941959 WITH s, f,
942960 CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
943961 CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
962+ CASE
963+ WHEN lower(coalesce(s.searchText, '')) CONTAINS (' ' || lower($query) || ' ')
964+ OR lower(coalesce(s.searchText, '')) STARTS WITH (lower($query) || ' ')
965+ OR lower(coalesce(s.searchText, '')) ENDS WITH (' ' || lower($query))
966+ THEN 0 ELSE 1
967+ END AS wordBoundaryRank,
944968 CASE
945969 WHEN f.relPath CONTAINS '/adapter/' THEN 2
946970 WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
947971 WHEN f.relPath STARTS WITH 'scripts/' THEN 2
948972 WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
973+ WHEN f.relPath CONTAINS 'target/' THEN 2
974+ WHEN f.relPath CONTAINS 'vendor/' THEN 2
949975 ELSE 0
950976 END AS filePenalty,
951977 CASE s.kind
@@ -963,8 +989,9 @@ async function searchSymbolsLiteSingleTerm(
963989 s.name AS name,
964990 f.fileId AS fileId,
965991 s.kind AS kind
966- ORDER BY exactNameRank, ciExactNameRank, filePenalty, kindRank, nameMatchRank` ,
967- { repoId, query : term } ,
992+ ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
993+ LIMIT $limit` ,
994+ { repoId, query : term , limit : 200 } ,
968995 ) ;
969996}
970997
0 commit comments