@@ -23,6 +23,7 @@ final _textSearchTimeout = Duration(milliseconds: 500);
2323class InMemoryPackageIndex {
2424 final List <PackageDocument > _documents;
2525 final _documentsByName = < String , PackageDocument > {};
26+ final _nameToIndex = < String , int > {};
2627 late final PackageNameIndex _packageNameIndex;
2728 late final TokenIndex <String > _descrIndex;
2829 late final TokenIndex <String > _readmeIndex;
@@ -62,6 +63,7 @@ class InMemoryPackageIndex {
6263 for (var i = 0 ; i < _documents.length; i++ ) {
6364 final doc = _documents[i];
6465 _documentsByName[doc.package] = doc;
66+ _nameToIndex[doc.package] = i;
6567
6668 // transform tags into numberical IDs
6769 final tagIds = < int > [];
@@ -232,7 +234,9 @@ class InMemoryPackageIndex {
232234 );
233235
234236 String ? bestNameMatch;
235- if (parsedQueryText != null ) {
237+ if (parsedQueryText != null &&
238+ query.parsedQuery.hasOnlyFreeText &&
239+ query.isNaturalOrder) {
236240 // exact package name
237241 if (_documentsByName.containsKey (parsedQueryText)) {
238242 bestNameMatch = parsedQueryText;
@@ -268,12 +272,18 @@ class InMemoryPackageIndex {
268272 /// it linearly into the [0.4-1.0] range, to allow better
269273 /// multiplication outcomes.
270274 packageScores.multiplyAllFromValues (_adjustedOverallScores);
271- indexedHits = _rankWithValues (packageScores,
272- requiredLengthThreshold: query.offset);
275+ indexedHits = _rankWithValues (
276+ packageScores,
277+ requiredLengthThreshold: query.offset,
278+ bestNameMatch: bestNameMatch,
279+ );
273280 break ;
274281 case SearchOrder .text:
275- indexedHits = _rankWithValues (packageScores,
276- requiredLengthThreshold: query.offset);
282+ indexedHits = _rankWithValues (
283+ packageScores,
284+ requiredLengthThreshold: query.offset,
285+ bestNameMatch: bestNameMatch,
286+ );
277287 break ;
278288 case SearchOrder .created:
279289 indexedHits = _createdOrderedHits.whereInScores (packageScores);
@@ -317,10 +327,14 @@ class InMemoryPackageIndex {
317327 packageHits = indexedHits.map ((h) => h.hit).toList ();
318328 }
319329
330+ // Only indicate name match when the first item's score is lower than the second's score.
331+ final indicateNameMatch = bestNameMatch != null &&
332+ packageHits.length > 1 &&
333+ ((packageHits[0 ].score ?? 0 ) <= (packageHits[1 ].score ?? 0 ));
320334 return PackageSearchResult (
321335 timestamp: clock.now ().toUtc (),
322336 totalCount: totalCount,
323- nameMatches: bestNameMatch == null ? null : [bestNameMatch],
337+ nameMatches: indicateNameMatch ? [bestNameMatch] : null ,
324338 packageHits: packageHits,
325339 errorMessage: textResults? .errorMessage,
326340 );
@@ -471,11 +485,14 @@ class InMemoryPackageIndex {
471485 IndexedScore <String > score, {
472486 // if the item count is fewer than this threshold, an empty list will be returned
473487 int ? requiredLengthThreshold,
488+ String ? bestNameMatch,
474489 }) {
475490 final list = < IndexedPackageHit > [];
491+ final bestNameIndex =
492+ bestNameMatch == null ? null : _nameToIndex[bestNameMatch];
476493 for (var i = 0 ; i < score.length; i++ ) {
477494 final value = score.getValue (i);
478- if (value <= 0.0 ) continue ;
495+ if (value <= 0.0 && i != bestNameIndex ) continue ;
479496 list.add (IndexedPackageHit (
480497 i, PackageHit (package: score.keys[i], score: value)));
481498 }
@@ -484,6 +501,8 @@ class InMemoryPackageIndex {
484501 return [];
485502 }
486503 list.sort ((a, b) {
504+ if (a.index == bestNameIndex) return - 1 ;
505+ if (b.index == bestNameIndex) return 1 ;
487506 final scoreCompare = - a.hit.score! .compareTo (b.hit.score! );
488507 if (scoreCompare != 0 ) return scoreCompare;
489508 // if two packages got the same score, order by last updated
0 commit comments