@@ -6,6 +6,7 @@ package meilisearch
6
6
import (
7
7
"context"
8
8
"errors"
9
+ "fmt"
9
10
"strconv"
10
11
"strings"
11
12
@@ -217,7 +218,14 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
217
218
218
219
skip , limit := indexer_internal .ParsePaginator (options .Paginator , maxTotalHits )
219
220
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 {
221
229
Filter : query .Statement (),
222
230
Limit : int64 (limit ),
223
231
Offset : int64 (skip ),
@@ -228,7 +236,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
228
236
return nil , err
229
237
}
230
238
231
- hits , err := nonFuzzyWorkaround (searchRes , options . Keyword , options . IsFuzzyKeyword )
239
+ hits , err := convertHits (searchRes )
232
240
if err != nil {
233
241
return nil , err
234
242
}
@@ -247,73 +255,32 @@ func parseSortBy(sortBy internal.SortBy) string {
247
255
return field + ":asc"
248
256
}
249
257
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 ) {
255
272
hits := make ([]internal.Match , 0 , len (searchRes .Hits ))
256
273
for _ , hit := range searchRes .Hits {
257
274
hit , ok := hit .(map [string ]any )
258
275
if ! ok {
259
276
return nil , ErrMalformedResponse
260
277
}
261
278
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
- }
313
279
issueID , ok := hit ["id" ].(float64 )
314
280
if ! ok {
315
281
return nil , ErrMalformedResponse
316
282
}
283
+
317
284
hits = append (hits , internal.Match {
318
285
ID : int64 (issueID ),
319
286
})
0 commit comments