1
1
{-# LANGUAGE BangPatterns, NamedFieldPuns, RecordWildCards #-}
2
+ {-# LANGUAGE ScopedTypeVariables #-}
2
3
3
4
module Distribution.Server.Features.Search.SearchEngine (
4
5
SearchEngine ,
@@ -55,7 +56,9 @@ data SearchConfig doc key field feature = SearchConfig {
55
56
documentKey :: doc -> key ,
56
57
extractDocumentTerms :: doc -> field -> [Term ],
57
58
transformQueryTerm :: Term -> field -> Term ,
58
- documentFeatureValue :: doc -> feature -> Float
59
+ documentFeatureValue :: doc -> feature -> Float ,
60
+ makeKey :: Term -> key
61
+
59
62
}
60
63
61
64
data SearchRankParameters field feature = SearchRankParameters {
@@ -204,11 +207,11 @@ deleteDoc key se@SearchEngine{searchIndex} =
204
207
updateCachedFieldLengths oldDoc Nothing $
205
208
se { searchIndex = searchIndex' }
206
209
207
- query :: (Ix field , Bounded field , Ix feature , Bounded feature ) =>
210
+ query :: (Ix field , Bounded field , Ix feature , Bounded feature , Ord key ) =>
208
211
SearchEngine doc key field feature ->
209
212
[Term ] -> [key ]
210
213
query se@ SearchEngine { searchIndex,
211
- searchConfig = SearchConfig {transformQueryTerm},
214
+ searchConfig = SearchConfig {transformQueryTerm, makeKey },
212
215
searchRankParams = SearchRankParameters {.. } }
213
216
terms =
214
217
@@ -223,9 +226,16 @@ query se@SearchEngine{ searchIndex,
223
226
]
224
227
225
228
-- Then we look up all the normalised terms in the index.
226
- rawresults :: [Maybe (TermId , DocIdSet )]
229
+ rawresults :: [Maybe (TermId , DocIdSet )]
227
230
rawresults = map (SI. lookupTerm searchIndex) lookupTerms
228
231
232
+ -- Check if there is one term then it exactly matches a package
233
+ exactMatch :: Maybe DocId
234
+ exactMatch = case terms of
235
+ [] -> Nothing
236
+ [x] -> SI. lookupDocKeyReal searchIndex (makeKey x)
237
+ (_: _) -> Nothing
238
+
229
239
-- For the terms that occur in the index, this gives us the term's id
230
240
-- and the set of documents that the term occurs in.
231
241
termids :: [TermId ]
@@ -254,17 +264,24 @@ query se@SearchEngine{ searchIndex,
254
264
-- What we ought to have instead is an Array (Int, field) TermId, and
255
265
-- make the scoring use the appropriate termid for each field, but to
256
266
-- consider them the "same" term.
257
- in rankResults se termids (DocIdSet. toList unrankedResults)
267
+ in rankResults se exactMatch termids (DocIdSet. toList unrankedResults)
258
268
259
- rankResults :: (Ix field , Bounded field , Ix feature , Bounded feature ) =>
260
- SearchEngine doc key field feature ->
269
+ rankResults :: forall field key feature doc .
270
+ (Ix field , Bounded field , Ix feature , Bounded feature ) =>
271
+ SearchEngine doc key field feature -> Maybe DocId ->
261
272
[TermId ] -> [DocId ] -> [key ]
262
- rankResults se@ SearchEngine {searchIndex} queryTerms docids =
263
- map snd
264
- $ sortBy (flip compare `on` fst )
273
+ rankResults se@ SearchEngine {searchIndex} exactMatch queryTerms docids =
274
+ maybe id prependExactMatch exactMatch ( map snd
275
+ $ sortBy (flip compare `on` fst )
265
276
[ (relevanceScore se queryTerms doctermids docfeatvals, dockey)
266
277
| docid <- docids
267
- , let (dockey, doctermids, docfeatvals) = SI. lookupDocId searchIndex docid ]
278
+ , maybe True (/= docid) exactMatch
279
+ , let (dockey, doctermids, docfeatvals) = SI. lookupDocId searchIndex docid ])
280
+ where
281
+ prependExactMatch :: DocId -> [key ] -> [key ]
282
+ prependExactMatch docid keys = dockey : keys
283
+ where
284
+ (dockey, _, _) = SI. lookupDocId searchIndex docid
268
285
269
286
relevanceScore :: (Ix field , Bounded field , Ix feature , Bounded feature ) =>
270
287
SearchEngine doc key field feature ->
0 commit comments