@@ -138,7 +138,7 @@ class InMemoryPackageIndex {
138
138
139
139
PackageSearchResult search (ServiceSearchQuery query) {
140
140
// prevent any work if offset is outside of the range
141
- if (( query.offset ?? 0 ) >= _documents.length) {
141
+ if (query.offset >= _documents.length) {
142
142
return PackageSearchResult .empty ();
143
143
}
144
144
return _bitArrayPool.withPoolItem (fn: (array) {
@@ -150,11 +150,10 @@ class InMemoryPackageIndex {
150
150
});
151
151
}
152
152
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) {
158
157
// filter on tags
159
158
final combinedTagsPredicate =
160
159
query.tagsPredicate.appendPredicate (query.parsedQuery.tagsPredicate);
@@ -164,7 +163,7 @@ class InMemoryPackageIndex {
164
163
if (entry.value) {
165
164
if (tagBits == null ) {
166
165
// the predicate is not matched by any document
167
- return PackageSearchResult . empty () ;
166
+ return 0 ;
168
167
}
169
168
packages.and (tagBits);
170
169
} else {
@@ -215,6 +214,19 @@ class InMemoryPackageIndex {
215
214
(i) => now.difference (_documents[i].updated) > updatedDuration);
216
215
}
217
216
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
+
218
230
// TODO: find a better way to handle predicate-only filtering and scoring
219
231
for (final index in packages.asIntIterable ()) {
220
232
if (index >= _documents.length) break ;
@@ -230,32 +242,7 @@ class InMemoryPackageIndex {
230
242
textMatchExtent: query.textMatchExtent ?? TextMatchExtent .api,
231
243
);
232
244
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);
259
246
260
247
List <IndexedPackageHit > indexedHits;
261
248
switch (query.effectiveOrder ?? SearchOrder .top) {
@@ -337,6 +324,42 @@ class InMemoryPackageIndex {
337
324
);
338
325
}
339
326
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
+
340
363
/// Update the overall score both on [PackageDocument] and in the [_adjustedOverallScores] map.
341
364
void _updateOverallScores () {
342
365
_adjustedOverallScores = _documents.map ((doc) {
0 commit comments