Skip to content

Commit f95baca

Browse files
authored
Merge pull request #16 from unisoncomputing/cp/search-names-prefix
Switch name search to return suffixes of prefixes.
2 parents 0aeb41d + d10bc48 commit f95baca

File tree

10 files changed

+57
-23
lines changed

10 files changed

+57
-23
lines changed

src/Share/Postgres/Search/DefinitionSearch/Queries.hs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Share.Postgres.Search.DefinitionSearch.Queries
66
claimUnsyncedRelease,
77
insertDefinitionDocuments,
88
cleanIndexForRelease,
9-
defNameSearch,
9+
defNameInfixSearch,
1010
definitionSearch,
1111
DefnNameSearchFilter (..),
1212
-- Exported for logging/debugging
@@ -266,8 +266,9 @@ data DefnNameSearchFilter
266266
| ReleaseFilter ReleaseId
267267
| UserFilter UserId
268268

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
271272
let filters = case mayFilter of
272273
Just (ProjectFilter projId) -> [sql| AND doc.project_id = #{projId} |]
273274
Just (ReleaseFilter relId) -> [sql| AND doc.release_id = #{relId} |]
@@ -280,10 +281,8 @@ defNameSearch mayCaller mayFilter (Query query) limit = do
280281
JOIN projects p ON p.id = doc.project_id
281282
JOIN project_releases r ON r.id = doc.release_id
282283
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}) || '%')
287286
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)))
288287
^{filters}
289288
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
292291
best_results(project_id, release_id, name, tag) AS (
293292
SELECT m.project_id, m.release_id, m.name, m.tag
294293
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
296297
LIMIT #{limit}
297298
)
298299
-- THEN sort docs to the bottom.
299300
SELECT br.project_id, br.release_id, br.name, br.tag
300301
FROM best_results br
301302
-- 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
303305
|]
304306

305307
definitionSearch :: Maybe UserId -> Maybe DefnNameSearchFilter -> Limit -> Set (DefnSearchToken (Either Name ShortHash)) -> Maybe Arity -> Transaction e [(ProjectId, ReleaseId, Name, TermOrTypeSummary)]

src/Share/Web/Share/Impl.hs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,36 @@ searchDefinitionNamesEndpoint ::
380380
Maybe IDs.ProjectShortHand ->
381381
Maybe IDs.ReleaseVersion ->
382382
WebApp [DefinitionNameSearchResult]
383-
searchDefinitionNamesEndpoint callerUserId query mayLimit userFilter projectFilter releaseFilter = do
383+
searchDefinitionNamesEndpoint callerUserId query@(Query queryText) mayLimit userFilter projectFilter releaseFilter = do
384384
filter <- runMaybeT $ resolveProjectAndReleaseFilter projectFilter releaseFilter <|> resolveUserFilter userFilter
385-
matches <- PG.runTransaction $ DDQ.defNameSearch callerUserId filter query limit
385+
matches <-
386+
(PG.runTransaction $ DDQ.defNameInfixSearch callerUserId filter query limit)
387+
<&> over (traversed . _3) (rewriteMatches queryText)
386388
let response = matches <&> \(_projId, _releaseId, name, tag) -> DefinitionNameSearchResult name tag
387389
pure response
388390
where
389391
limit = fromMaybe (Limit 20) mayLimit
390392

393+
-- Try to rewrite the name to only include the part of the name that matches the query,
394+
-- and any following suffix.
395+
-- >>> Name.toText $ rewriteMatches "foo" (Name.unsafeParseText "foo.bar.baz")
396+
-- "foo.bar.baz"
397+
--
398+
-- >>> Name.toText $ rewriteMatches "List.ma" (Name.unsafeParseText "data.List.map")
399+
-- "List.map"
400+
--
401+
-- No match; we shouldn't get these back from the query, but if we do, just return the name as is.
402+
-- >>> Name.toText $ rewriteMatches "foo" (Name.unsafeParseText "bar.baz")
403+
-- "bar.baz"
404+
rewriteMatches :: Text -> Name -> Name
405+
rewriteMatches q name
406+
| nameText <- Name.toText name,
407+
Text.isInfixOf q nameText =
408+
let (_before, after) = Text.breakOnEnd q nameText
409+
in Name.parseText (q <> after)
410+
& fromMaybe name
411+
| otherwise = name
412+
391413
resolveProjectAndReleaseFilter :: Maybe IDs.ProjectShortHand -> Maybe IDs.ReleaseVersion -> MaybeT WebApp DDQ.DefnNameSearchFilter
392414
resolveProjectAndReleaseFilter projectFilter releaseFilter = do
393415
projectShortHand <- hoistMaybe projectFilter

transcripts/share-apis/search/complex-type-mention-search.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
},
146146
"tag": "Plain"
147147
},
148-
"fqn": "List.map",
148+
"fqn": "data.List.map",
149149
"kind": "term",
150150
"projectRef": "@transcripts/search"
151151
}

transcripts/share-apis/search/create-release.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"body": {
3-
"causalHashSquashed": "#k64a0e0j4goec5ktrql2q8knot22dakbks05kno7jvr5fha3c894o6hhbkusi7tqegk024d9trmh0v7hikbjn6rrsura5tuecg1bt8o",
4-
"causalHashUnsquashed": "#1d13nals2i51pbupql9vm16qqsvr9svld305f5uijrslk26vuqunq9sd3mqqsn8lsecgocdmn7fr7cujgppsp3lie9j1fc68mfeua28",
3+
"causalHashSquashed": "#kgss2635bbm50dqgut16165dpivfb9tfecrpijpoc018699fti92jf9e8bh9pr3fe18qbnk1h70g9fj1oh6j3ea0gsia3rocee286k0",
4+
"causalHashUnsquashed": "#41ut9c720q056bp558lo9in3jlo3p75f9hrt3b5hv3nqdmtitr79aihkmk4p0vsh2g4o2kdd3nts5gskmpagceti5rbtunilghdgi58",
55
"createdAt": "<TIMESTAMP>",
66
"createdBy": "@transcripts",
77
"projectRef": "@transcripts/search",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"body": [
3+
{
4+
"tag": "plain",
5+
"token": "List.map"
6+
}
7+
],
8+
"status": [
9+
{
10+
"status_code": 200
11+
}
12+
]
13+
}

transcripts/share-apis/search/name-search-suffix.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@
22
"body": [
33
{
44
"tag": "plain",
5-
"token": "function.const"
6-
},
7-
{
8-
"tag": "data-constructor",
9-
"token": "data.List.Cons"
5+
"token": "const"
106
}
117
],
128
"status": [

transcripts/share-apis/search/prelude.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ function.const a b = a
1515
structural ability Throw e where
1616
throw : e -> a
1717
18-
List.map : (a -> {g} b) -> List a -> {g} List b
19-
List.map f = cases
18+
data.List.map : (a -> {g} b) -> List a -> {g} List b
19+
data.List.map f = cases
2020
(Cons a rest) -> Cons (f a) (List.map f rest)
2121
Nil -> Nil
2222

transcripts/share-apis/search/run.zsh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ done
3838
# Name searches
3939
fetch "$transcript_user" GET 'name-search-suffix' '/search-names?query=const'
4040
fetch "$transcript_user" GET 'name-search-prefix' '/search-names?query=Func'
41+
fetch "$transcript_user" GET 'name-search-infix' '/search-names?query=List.ma'
4142

4243
# Type searches
4344
# "b -> a -> a"

transcripts/share-apis/search/similar-type-search.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
},
146146
"tag": "Plain"
147147
},
148-
"fqn": "List.map",
148+
"fqn": "data.List.map",
149149
"kind": "term",
150150
"projectRef": "@transcripts/search"
151151
}

transcripts/share-apis/search/type-var-search.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
},
208208
"tag": "Plain"
209209
},
210-
"fqn": "List.map",
210+
"fqn": "data.List.map",
211211
"kind": "term",
212212
"projectRef": "@transcripts/search"
213213
}

0 commit comments

Comments
 (0)