Skip to content

Commit b47046e

Browse files
authored
Support negative keywords in queries (#982)
* Support negative keywords in queries * Preserve order in List.Extra.unique
1 parent 8a974ef commit b47046e

File tree

2 files changed

+82
-40
lines changed

2 files changed

+82
-40
lines changed

frontend/src/List/Extra.elm

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
module List.Extra exposing (find)
1+
module List.Extra exposing (find, unique)
2+
3+
import Set
24

35

46
find : (a -> Bool) -> List a -> Maybe a
@@ -13,3 +15,19 @@ find p list =
1315

1416
else
1517
find p t
18+
19+
20+
unique : List comparable -> List comparable
21+
unique list =
22+
list
23+
|> List.foldl
24+
(\e ( lst, set ) ->
25+
if Set.member e set then
26+
( lst, set )
27+
28+
else
29+
( e :: lst, Set.insert e set )
30+
)
31+
( [], Set.empty )
32+
|> Tuple.first
33+
|> List.reverse

frontend/src/Search.elm

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import Http
7979
import Json.Decode
8080
import Json.Decode.Pipeline
8181
import Json.Encode
82+
import List.Extra
8283
import RemoteData
8384
import Route
8485
exposing
@@ -87,7 +88,6 @@ import Route
8788
, searchTypeToTitle
8889
)
8990
import Route.SearchQuery
90-
import Set
9191
import Task
9292

9393

@@ -1245,12 +1245,13 @@ filterByType type_ =
12451245

12461246

12471247
searchFields :
1248-
String
1248+
List String
12491249
-> String
12501250
-> List ( String, Float )
12511251
-> List (List ( String, Json.Encode.Value ))
1252-
searchFields query mainField fields =
1252+
searchFields positiveWords mainField fields =
12531253
let
1254+
allFields : List String
12541255
allFields =
12551256
fields
12561257
|> List.concatMap
@@ -1260,44 +1261,28 @@ searchFields query mainField fields =
12601261
]
12611262
)
12621263

1264+
queryWordsWildCard : List String
12631265
queryWordsWildCard =
1264-
(String.replace "_" "-" query :: String.replace "-" "_" query :: queryWords)
1265-
|> Set.fromList
1266-
|> Set.toList
1266+
positiveWords
1267+
|> List.concatMap dashUnderscoreVariants
1268+
|> List.Extra.unique
12671269

1268-
queryWords =
1269-
String.words (String.toLower query)
1270+
multiMatch : List ( String, Json.Encode.Value )
1271+
multiMatch =
1272+
[ ( "multi_match"
1273+
, Json.Encode.object
1274+
[ ( "type", Json.Encode.string "cross_fields" )
1275+
, ( "query", Json.Encode.string (String.join " " positiveWords) )
1276+
, ( "analyzer", Json.Encode.string "whitespace" )
1277+
, ( "auto_generate_synonyms_phrase_query", Json.Encode.bool False )
1278+
, ( "operator", Json.Encode.string "and" )
1279+
, ( "_name", Json.Encode.string <| "multi_match_" ++ String.join "_" positiveWords )
1280+
, ( "fields", Json.Encode.list Json.Encode.string allFields )
1281+
]
1282+
)
1283+
]
12701284
in
1271-
List.append
1272-
[ [ ( "multi_match"
1273-
, Json.Encode.object
1274-
[ ( "type", Json.Encode.string "cross_fields" )
1275-
, ( "query", Json.Encode.string <| String.join " " queryWords )
1276-
, ( "analyzer", Json.Encode.string "whitespace" )
1277-
, ( "auto_generate_synonyms_phrase_query", Json.Encode.bool False )
1278-
, ( "operator", Json.Encode.string "and" )
1279-
, ( "_name", Json.Encode.string <| "multi_match_" ++ String.join "_" queryWords )
1280-
, ( "fields", Json.Encode.list Json.Encode.string allFields )
1281-
]
1282-
)
1283-
]
1284-
]
1285-
(List.map
1286-
(\queryWord ->
1287-
[ ( "wildcard"
1288-
, Json.Encode.object
1289-
[ ( mainField
1290-
, Json.Encode.object
1291-
[ ( "value", Json.Encode.string ("*" ++ queryWord ++ "*") )
1292-
, ( "case_insensitive", Json.Encode.bool True )
1293-
]
1294-
)
1295-
]
1296-
)
1297-
]
1298-
)
1299-
queryWordsWildCard
1300-
)
1285+
multiMatch :: List.map (toWildcardQuery mainField) queryWordsWildCard
13011286

13021287

13031288
makeRequestBody :
@@ -1322,6 +1307,12 @@ makeRequestBody query from sizeRaw sort type_ sortField otherSortFields bucketsF
13221307

13231308
else
13241309
sizeRaw
1310+
1311+
( negativeWords, positiveWords ) =
1312+
String.toLower query
1313+
|> String.words
1314+
|> List.partition (String.startsWith "-")
1315+
|> Tuple.mapFirst (List.map (String.dropLeft 1))
13251316
in
13261317
Http.jsonBody
13271318
(Json.Encode.object
@@ -1349,14 +1340,22 @@ makeRequestBody query from sizeRaw sort type_ sortField otherSortFields bucketsF
13491340
)
13501341
)
13511342
)
1343+
, ( "must_not"
1344+
, Json.Encode.list Json.Encode.object
1345+
(negativeWords
1346+
|> List.concatMap dashUnderscoreVariants
1347+
|> List.Extra.unique
1348+
|> List.map (toWildcardQuery mainField)
1349+
)
1350+
)
13521351
, ( "must"
13531352
, Json.Encode.list Json.Encode.object
13541353
[ [ ( "dis_max"
13551354
, Json.Encode.object
13561355
[ ( "tie_breaker", Json.Encode.float 0.7 )
13571356
, ( "queries"
13581357
, Json.Encode.list Json.Encode.object
1359-
(searchFields query mainField fields)
1358+
(searchFields positiveWords mainField fields)
13601359
)
13611360
]
13621361
)
@@ -1371,6 +1370,31 @@ makeRequestBody query from sizeRaw sort type_ sortField otherSortFields bucketsF
13711370
)
13721371

13731372

1373+
{-| Given a word, returns all variants of replacing underscores and dashes with each other.
1374+
-}
1375+
dashUnderscoreVariants : String -> List String
1376+
dashUnderscoreVariants word =
1377+
[ String.replace "_" "-" word
1378+
, String.replace "-" "_" word
1379+
, word
1380+
]
1381+
1382+
1383+
toWildcardQuery : String -> String -> List ( String, Json.Encode.Value )
1384+
toWildcardQuery mainField queryWord =
1385+
[ ( "wildcard"
1386+
, Json.Encode.object
1387+
[ ( mainField
1388+
, Json.Encode.object
1389+
[ ( "value", Json.Encode.string ("*" ++ queryWord ++ "*") )
1390+
, ( "case_insensitive", Json.Encode.bool True )
1391+
]
1392+
)
1393+
]
1394+
)
1395+
]
1396+
1397+
13741398
makeRequest :
13751399
Http.Body
13761400
-> List NixOSChannel

0 commit comments

Comments
 (0)