Skip to content

Commit cf0f17e

Browse files
committed
Place exact package matches at the start of search results.
Closes #397
1 parent e0bd7fc commit cf0f17e

File tree

3 files changed

+38
-16
lines changed

3 files changed

+38
-16
lines changed

Distribution/Server/Features/Search/PkgSearch.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import NLP.Snowball
2222
import Distribution.Package
2323
import Distribution.PackageDescription
2424
import Distribution.Text (display)
25+
import Data.Text (unpack)
2526

2627

2728
type PkgSearchEngine = SearchEngine
@@ -50,7 +51,8 @@ pkgSearchConfig =
5051
documentKey = packageName . fst,
5152
extractDocumentTerms = extractTokens . fst,
5253
transformQueryTerm = normaliseQueryToken,
53-
documentFeatureValue = getFeatureValue
54+
documentFeatureValue = getFeatureValue,
55+
makeKey = PackageName . unpack
5456
}
5557
where
5658
extractTokens :: PackageDescription -> PkgDocField -> [Text]

Distribution/Server/Features/Search/SearchEngine.hs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE BangPatterns, NamedFieldPuns, RecordWildCards #-}
2+
{-# LANGUAGE ScopedTypeVariables #-}
23

34
module Distribution.Server.Features.Search.SearchEngine (
45
SearchEngine,
@@ -55,7 +56,9 @@ data SearchConfig doc key field feature = SearchConfig {
5556
documentKey :: doc -> key,
5657
extractDocumentTerms :: doc -> field -> [Term],
5758
transformQueryTerm :: Term -> field -> Term,
58-
documentFeatureValue :: doc -> feature -> Float
59+
documentFeatureValue :: doc -> feature -> Float,
60+
makeKey :: Term -> key
61+
5962
}
6063

6164
data SearchRankParameters field feature = SearchRankParameters {
@@ -204,11 +207,11 @@ deleteDoc key se@SearchEngine{searchIndex} =
204207
updateCachedFieldLengths oldDoc Nothing $
205208
se { searchIndex = searchIndex' }
206209

207-
query :: (Ix field, Bounded field, Ix feature, Bounded feature) =>
210+
query :: (Ix field, Bounded field, Ix feature, Bounded feature, Ord key) =>
208211
SearchEngine doc key field feature ->
209212
[Term] -> [key]
210213
query se@SearchEngine{ searchIndex,
211-
searchConfig = SearchConfig{transformQueryTerm},
214+
searchConfig = SearchConfig{transformQueryTerm, makeKey},
212215
searchRankParams = SearchRankParameters{..} }
213216
terms =
214217

@@ -223,9 +226,16 @@ query se@SearchEngine{ searchIndex,
223226
]
224227

225228
-- Then we look up all the normalised terms in the index.
226-
rawresults :: [Maybe (TermId, DocIdSet)]
229+
rawresults :: [Maybe (TermId, DocIdSet)]
227230
rawresults = map (SI.lookupTerm searchIndex) lookupTerms
228231

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+
229239
-- For the terms that occur in the index, this gives us the term's id
230240
-- and the set of documents that the term occurs in.
231241
termids :: [TermId]
@@ -254,17 +264,24 @@ query se@SearchEngine{ searchIndex,
254264
-- What we ought to have instead is an Array (Int, field) TermId, and
255265
-- make the scoring use the appropriate termid for each field, but to
256266
-- consider them the "same" term.
257-
in rankResults se termids (DocIdSet.toList unrankedResults)
267+
in rankResults se exactMatch termids (DocIdSet.toList unrankedResults)
258268

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 ->
261272
[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)
265276
[ (relevanceScore se queryTerms doctermids docfeatvals, dockey)
266277
| 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
268285

269286
relevanceScore :: (Ix field, Bounded field, Ix feature, Bounded feature) =>
270287
SearchEngine doc key field feature ->

Distribution/Server/Features/Search/SearchIndex.hs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ module Distribution.Server.Features.Search.SearchIndex (
1515
lookupTermId,
1616
lookupDocId,
1717
lookupDocKey,
18-
18+
lookupDocKeyReal,
19+
1920
getTerm,
20-
21+
2122
invariant,
2223
) where
2324

@@ -170,14 +171,16 @@ lookupDocId SearchIndex{docIdMap} docid =
170171
errNotFound = error $ "lookupDocId: not found " ++ show docid
171172

172173
lookupDocKey :: Ord key => SearchIndex key field feature -> key -> Maybe (DocTermIds field)
173-
lookupDocKey SearchIndex{docKeyMap, docIdMap} key = do
174+
lookupDocKey SearchIndex{docKeyMap, docIdMap} key =
174175
case Map.lookup key docKeyMap of
175176
Nothing -> Nothing
176177
Just docid ->
177178
case IntMap.lookup (fromEnum docid) docIdMap of
178179
Nothing -> error "lookupDocKey: internal error"
179-
Just (DocInfo _key doctermids _) -> Just doctermids
180+
Just (DocInfo _ doctermids _) -> Just doctermids
180181

182+
lookupDocKeyReal :: Ord key => SearchIndex key field feature -> key -> Maybe DocId
183+
lookupDocKeyReal SearchIndex{docKeyMap} key = Map.lookup key docKeyMap
181184

182185
getTerm :: SearchIndex key field feature -> TermId -> Term
183186
getTerm SearchIndex{termIdMap} termId =

0 commit comments

Comments
 (0)