@@ -138,7 +138,7 @@ class InMemoryPackageIndex {
138138
139139 PackageSearchResult search (ServiceSearchQuery query) {
140140 // prevent any work if offset is outside of the range
141- if (( query.offset ?? 0 ) >= _documents.length) {
141+ if (query.offset >= _documents.length) {
142142 return PackageSearchResult .empty ();
143143 }
144144 return _bitArrayPool.withPoolItem (fn: (array) {
@@ -150,11 +150,10 @@ class InMemoryPackageIndex {
150150 });
151151 }
152152
153- PackageSearchResult _search (
154- ServiceSearchQuery query,
155- BitArray packages,
156- IndexedScore <String > packageScores,
157- ) {
153+ /// Filters on query predicates with fast bitmap operations.
154+ /// Returns 0 if no document matches the query, or the number
155+ /// of documents that matches the predicates so far.
156+ int _filterOnPredicates (ServiceSearchQuery query, BitArray packages) {
158157 // filter on tags
159158 final combinedTagsPredicate =
160159 query.tagsPredicate.appendPredicate (query.parsedQuery.tagsPredicate);
@@ -164,7 +163,7 @@ class InMemoryPackageIndex {
164163 if (entry.value) {
165164 if (tagBits == null ) {
166165 // the predicate is not matched by any document
167- return PackageSearchResult . empty () ;
166+ return 0 ;
168167 }
169168 packages.and (tagBits);
170169 } else {
@@ -215,6 +214,19 @@ class InMemoryPackageIndex {
215214 (i) => now.difference (_documents[i].updated) > updatedDuration);
216215 }
217216
217+ return packages.cardinality;
218+ }
219+
220+ PackageSearchResult _search (
221+ ServiceSearchQuery query,
222+ BitArray packages,
223+ IndexedScore <String > packageScores,
224+ ) {
225+ final predicateFilterCount = _filterOnPredicates (query, packages);
226+ if (predicateFilterCount <= query.offset) {
227+ return PackageSearchResult .empty ();
228+ }
229+
218230 // TODO: find a better way to handle predicate-only filtering and scoring
219231 for (final index in packages.asIntIterable ()) {
220232 if (index >= _documents.length) break ;
@@ -230,32 +242,7 @@ class InMemoryPackageIndex {
230242 textMatchExtent: query.textMatchExtent ?? TextMatchExtent .api,
231243 );
232244
233- String ? bestNameMatch;
234- if (parsedQueryText != null &&
235- query.parsedQuery.hasOnlyFreeText &&
236- query.isNaturalOrder) {
237- // exact package name
238- if (_documentsByName.containsKey (parsedQueryText)) {
239- bestNameMatch = parsedQueryText;
240- } else {
241- // reduced package name match
242- final matches = _packageNameIndex.lookupMatchingNames (parsedQueryText);
243- if (matches != null && matches.isNotEmpty) {
244- bestNameMatch = matches.length == 1
245- ? matches.single
246- :
247- // Note: to keep it simple, we select the most downloaded one from competing matches.
248- matches.reduce ((a, b) {
249- if (_documentsByName[a]! .downloadCount >
250- _documentsByName[b]! .downloadCount) {
251- return a;
252- } else {
253- return b;
254- }
255- });
256- }
257- }
258- }
245+ final bestNameMatch = _bestNameMatch (query);
259246
260247 List <IndexedPackageHit > indexedHits;
261248 switch (query.effectiveOrder ?? SearchOrder .top) {
@@ -337,6 +324,42 @@ class InMemoryPackageIndex {
337324 );
338325 }
339326
327+ /// Returns the package name that is considered as the best name match
328+ /// for the [query] , or `null` if there is no such package name, or the
329+ /// match is not enabled for the given context (e.g. non-default ordering).
330+ String ? _bestNameMatch (ServiceSearchQuery query) {
331+ final parsedQueryText = query.parsedQuery.text;
332+ if (parsedQueryText == null ) {
333+ return null ;
334+ }
335+ if (! query.parsedQuery.hasOnlyFreeText || ! query.isNaturalOrder) {
336+ return null ;
337+ }
338+
339+ // exact package name
340+ if (_documentsByName.containsKey (parsedQueryText)) {
341+ return parsedQueryText;
342+ }
343+
344+ // reduced package name match
345+ final matches = _packageNameIndex.lookupMatchingNames (parsedQueryText);
346+ if (matches == null || matches.isEmpty) {
347+ return null ;
348+ }
349+ if (matches.length == 1 ) {
350+ return matches.single;
351+ }
352+ // Note: to keep it simple, we select the most downloaded one from competing matches.
353+ return matches.reduce ((a, b) {
354+ if (_documentsByName[a]! .downloadCount >
355+ _documentsByName[b]! .downloadCount) {
356+ return a;
357+ } else {
358+ return b;
359+ }
360+ });
361+ }
362+
340363 /// Update the overall score both on [PackageDocument] and in the [_adjustedOverallScores] map.
341364 void _updateOverallScores () {
342365 _adjustedOverallScores = _documents.map ((doc) {
0 commit comments