@@ -6,7 +6,7 @@ module Share.Postgres.Search.DefinitionSearch.Queries
6
6
claimUnsyncedRelease ,
7
7
insertDefinitionDocuments ,
8
8
cleanIndexForRelease ,
9
- defNameSearch ,
9
+ defNameInfixSearch ,
10
10
definitionSearch ,
11
11
DefnNameSearchFilter (.. ),
12
12
-- Exported for logging/debugging
@@ -266,8 +266,9 @@ data DefnNameSearchFilter
266
266
| ReleaseFilter ReleaseId
267
267
| UserFilter UserId
268
268
269
- defNameSearch :: Maybe UserId -> Maybe DefnNameSearchFilter -> Query -> Limit -> Transaction e [(ProjectId , ReleaseId , Name , TermOrTypeTag )]
270
- defNameSearch mayCaller mayFilter (Query query) limit = do
269
+ -- | Find definitions whose name contains the query.
270
+ defNameInfixSearch :: Maybe UserId -> Maybe DefnNameSearchFilter -> Query -> Limit -> Transaction e [(ProjectId , ReleaseId , Name , TermOrTypeTag )]
271
+ defNameInfixSearch mayCaller mayFilter (Query query) limit = do
271
272
let filters = case mayFilter of
272
273
Just (ProjectFilter projId) -> [sql | AND doc.project_id = #{projId} |]
273
274
Just (ReleaseFilter relId) -> [sql | AND doc.release_id = #{relId} |]
@@ -280,10 +281,8 @@ defNameSearch mayCaller mayFilter (Query query) limit = do
280
281
JOIN projects p ON p.id = doc.project_id
281
282
JOIN project_releases r ON r.id = doc.release_id
282
283
WHERE
283
- -- Search name by a trigram 'word similarity'
284
- -- which will match if the query is similar to any 'word' (e.g. name segment)
285
- -- in the name.
286
- #{query} <% doc.name
284
+ -- Find names which contain the query
285
+ doc.name ILIKE ('%' || like_escape(#{query}) || '%')
287
286
AND (NOT p.private OR (#{mayCaller} IS NOT NULL AND EXISTS (SELECT FROM accessible_private_projects pp WHERE pp.user_id = #{mayCaller} AND pp.project_id = p.id)))
288
287
^{filters}
289
288
ORDER BY doc.project_id, doc.name, r.major_version, r.minor_version, r.patch_version
@@ -292,14 +291,17 @@ defNameSearch mayCaller mayFilter (Query query) limit = do
292
291
best_results(project_id, release_id, name, tag) AS (
293
292
SELECT m.project_id, m.release_id, m.name, m.tag
294
293
FROM matches_deduped_by_project m
295
- ORDER BY similarity(#{query}, m.name) DESC
294
+ -- Prefer matches where the query is near the end of the name,
295
+ -- e.g. for query 'List', 'data.List' should come before 'data.List.map'
296
+ ORDER BY length(m.name) - position(#{query} in m.name) ASC
296
297
LIMIT #{limit}
297
298
)
298
299
-- THEN sort docs to the bottom.
299
300
SELECT br.project_id, br.release_id, br.name, br.tag
300
301
FROM best_results br
301
302
-- docs and tests to the bottom, but otherwise sort by quality of the match.
302
- ORDER BY (br.tag <> 'doc'::definition_tag, br.tag <> 'test'::definition_tag, br.name LIKE ('%' || like_escape(#{query})), similarity(#{query}, br.name)) DESC
303
+ ORDER BY br.tag <> 'doc'::definition_tag, br.tag <> 'test'::definition_tag DESC,
304
+ length(br.name) - position(#{query} in br.name) ASC
303
305
|]
304
306
305
307
definitionSearch :: Maybe UserId -> Maybe DefnNameSearchFilter -> Limit -> Set (DefnSearchToken (Either Name ShortHash )) -> Maybe Arity -> Transaction e [(ProjectId , ReleaseId , Name , TermOrTypeSummary )]
0 commit comments