@@ -28,7 +28,7 @@ class InMemoryPackageIndex {
2828 late final TokenIndex <String > _readmeIndex;
2929 late final TokenIndex <IndexedApiDocPage > _apiSymbolIndex;
3030 late final _scorePool = ScorePool (_packageNameIndex._packageNames);
31- final _tagIds = < String , int > {};
31+ final _tagDocumentIndexes = < String , List < int > > {};
3232 final _documentTagIds = < List <int >> [];
3333
3434 /// Adjusted score takes the overall score and transforms
@@ -63,7 +63,7 @@ class InMemoryPackageIndex {
6363 // transform tags into numberical IDs
6464 final tagIds = < int > [];
6565 for (final tag in doc.tags) {
66- tagIds. add (_tagIds. putIfAbsent (tag, () => _tagIds.length) );
66+ _tagDocumentIndexes. putIfAbsent (tag, () => []). add (i );
6767 }
6868 tagIds.sort ();
6969 _documentTagIds.add (tagIds);
@@ -134,11 +134,7 @@ class InMemoryPackageIndex {
134134 PackageSearchResult search (ServiceSearchQuery query) {
135135 // prevent any work if offset is outside of the range
136136 if ((query.offset ?? 0 ) > _documents.length) {
137- return PackageSearchResult (
138- timestamp: clock.now (),
139- totalCount: 0 ,
140- packageHits: [],
141- );
137+ return PackageSearchResult .empty ();
142138 }
143139 return _scorePool.withScore (
144140 value: 1.0 ,
@@ -162,49 +158,36 @@ class InMemoryPackageIndex {
162158 final combinedTagsPredicate =
163159 query.tagsPredicate.appendPredicate (query.parsedQuery.tagsPredicate);
164160 if (combinedTagsPredicate.isNotEmpty) {
165- // The list of predicate tag entries, converted to tag IDs (or -1 if there is no indexed tag),
166- // sorted by their id.
167- final entriesToCheck = combinedTagsPredicate.entries
168- .map ((e) => MapEntry (_tagIds[e.key] ?? - 1 , e.value))
169- .toList ()
170- ..sort ((a, b) => a.key.compareTo (b.key));
171-
172- packageScores.retainWhere ((docIndex, _) {
173- // keeping track of tag id iteration with the `nextTagIndex`
174- final tagIds = _documentTagIds[docIndex];
175- var nextTagIndex = 0 ;
176-
177- for (final entry in entriesToCheck) {
178- if (entry.key == - 1 ) {
179- // no tag id is present for this predicate
180- if (entry.value) {
181- // the predicate is required, no document will match it
182- return false ;
183- } else {
184- // the predicate is prohibited, no document has it, always a match
161+ for (final entry in combinedTagsPredicate.entries) {
162+ final docIndexes = _tagDocumentIndexes[entry.key];
163+
164+ if (entry.value) {
165+ // predicate is required, zeroing the gaps between index values
166+ if (docIndexes == null ) {
167+ // the predicate is required, no document will match it
168+ return PackageSearchResult .empty ();
169+ }
170+
171+ for (var i = 0 ; i < docIndexes.length; i++ ) {
172+ if (i == 0 ) {
173+ packageScores.fillRange (0 , docIndexes[i], 0.0 );
185174 continue ;
186175 }
176+ packageScores.fillRange (docIndexes[i - 1 ] + 1 , docIndexes[i], 0.0 );
187177 }
178+ packageScores.fillRange (docIndexes.last + 1 , _documents.length, 0.0 );
179+ } else {
180+ // predicate is prohibited, zeroing the values
188181
189- // skipping the present tag ids until the currently matched predicate tag id
190- while (nextTagIndex < tagIds.length &&
191- tagIds[nextTagIndex] < entry.key) {
192- nextTagIndex++ ;
182+ if (docIndexes == null ) {
183+ // the predicate is prohibited, no document has it, always a match
184+ continue ;
193185 }
194-
195- // checking presence
196- late bool present;
197- if (nextTagIndex == tagIds.length) {
198- present = false ;
199- } else {
200- present = tagIds[nextTagIndex] == entry.key;
186+ for (final i in docIndexes) {
187+ packageScores.setValue (i, 0.0 );
201188 }
202-
203- if (entry.value && ! present) return false ;
204- if (! entry.value && present) return false ;
205189 }
206- return true ;
207- });
190+ }
208191 }
209192
210193 // filter on dependency
0 commit comments