@@ -6,6 +6,7 @@ package meilisearch
66import (
77 "context"
88 "errors"
9+ "fmt"
910 "strconv"
1011 "strings"
1112
@@ -217,7 +218,14 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
217218
218219 skip , limit := indexer_internal .ParsePaginator (options .Paginator , maxTotalHits )
219220
220- searchRes , err := b .inner .Client .Index (b .inner .VersionedIndexName ()).Search (options .Keyword , & meilisearch.SearchRequest {
221+ keyword := options .Keyword
222+ if ! options .IsFuzzyKeyword {
223+ // to make it non fuzzy ("typo tolerance" in meilisearch terms), we have to quote the keyword(s)
224+ // https://www.meilisearch.com/docs/reference/api/search#phrase-search
225+ keyword = doubleQuoteKeyword (keyword )
226+ }
227+
228+ searchRes , err := b .inner .Client .Index (b .inner .VersionedIndexName ()).Search (keyword , & meilisearch.SearchRequest {
221229 Filter : query .Statement (),
222230 Limit : int64 (limit ),
223231 Offset : int64 (skip ),
@@ -228,7 +236,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
228236 return nil , err
229237 }
230238
231- hits , err := nonFuzzyWorkaround (searchRes , options . Keyword , options . IsFuzzyKeyword )
239+ hits , err := convertHits (searchRes )
232240 if err != nil {
233241 return nil , err
234242 }
@@ -247,73 +255,32 @@ func parseSortBy(sortBy internal.SortBy) string {
247255 return field + ":asc"
248256}
249257
250- // nonFuzzyWorkaround is needed as meilisearch does not have an exact search
251- // and you can only change "typo tolerance" per index. So we have to post-filter the results
252- // https://www.meilisearch.com/docs/learn/configuration/typo_tolerance#configuring-typo-tolerance
253- // TODO: remove once https://github.com/orgs/meilisearch/discussions/377 is addressed
254- func nonFuzzyWorkaround (searchRes * meilisearch.SearchResponse , keyword string , isFuzzy bool ) ([]internal.Match , error ) {
258+ func doubleQuoteKeyword (k string ) string {
259+ kp := strings .Split (k , " " )
260+ parts := 0
261+ for i := range kp {
262+ part := strings .Trim (kp [i ], "\" " )
263+ if part != "" {
264+ kp [parts ] = fmt .Sprintf (`"%s"` , part )
265+ parts ++
266+ }
267+ }
268+ return strings .Join (kp [:parts ], " " )
269+ }
270+
271+ func convertHits (searchRes * meilisearch.SearchResponse ) ([]internal.Match , error ) {
255272 hits := make ([]internal.Match , 0 , len (searchRes .Hits ))
256273 for _ , hit := range searchRes .Hits {
257274 hit , ok := hit .(map [string ]any )
258275 if ! ok {
259276 return nil , ErrMalformedResponse
260277 }
261278
262- if ! isFuzzy {
263- keyword = strings .ToLower (keyword )
264-
265- // declare a anon func to check if the title, content or at least one comment contains the keyword
266- found , err := func () (bool , error ) {
267- // check if title match first
268- title , ok := hit ["title" ].(string )
269- if ! ok {
270- return false , ErrMalformedResponse
271- } else if strings .Contains (strings .ToLower (title ), keyword ) {
272- return true , nil
273- }
274-
275- // check if content has a match
276- content , ok := hit ["content" ].(string )
277- if ! ok {
278- return false , ErrMalformedResponse
279- } else if strings .Contains (strings .ToLower (content ), keyword ) {
280- return true , nil
281- }
282-
283- // now check for each comment if one has a match
284- // so we first try to cast and skip if there are no comments
285- comments , ok := hit ["comments" ].([]any )
286- if ! ok {
287- return false , ErrMalformedResponse
288- } else if len (comments ) == 0 {
289- return false , nil
290- }
291-
292- // now we iterate over all and report as soon as we detect one match
293- for i := range comments {
294- comment , ok := comments [i ].(string )
295- if ! ok {
296- return false , ErrMalformedResponse
297- }
298- if strings .Contains (strings .ToLower (comment ), keyword ) {
299- return true , nil
300- }
301- }
302-
303- // we got no match
304- return false , nil
305- }()
306-
307- if err != nil {
308- return nil , err
309- } else if ! found {
310- continue
311- }
312- }
313279 issueID , ok := hit ["id" ].(float64 )
314280 if ! ok {
315281 return nil , ErrMalformedResponse
316282 }
283+
317284 hits = append (hits , internal.Match {
318285 ID : int64 (issueID ),
319286 })
0 commit comments