@@ -209,6 +209,7 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
209
209
210
210
var modes map [uint8 ]* uint8
211
211
var labelResults * bleve.SearchResult
212
+ var orderRequired bool
212
213
if query != nil {
213
214
if authoritative != nil && ! authoritative .Value {
214
215
// A filter on query is requested but authoritative matches are not allowed.
@@ -241,6 +242,8 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
241
242
242
243
// Because we have a query filter only authoritative matches are eligible.
243
244
modes = MatchFilterAuthoritative
245
+ // The query may contain boosting, in which case the order of results matters.
246
+ orderRequired = true
244
247
} else if label != nil {
245
248
if authoritative != nil && ! authoritative .Value {
246
249
// A filter on label is requested but authoritative matches are not allowed.
@@ -302,6 +305,63 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
302
305
return make ([]* api.Match , 0 ), nil
303
306
}
304
307
308
+ // There is a query which may contain boosted search terms, which means order of results matters.
309
+ if orderRequired {
310
+ // Look up tracker info to determine match sizes.
311
+ // This info is needed even if there is no min/max size filter because it's returned in results.
312
+ matches := r .tracker .CountByStreamModeFilter (modes )
313
+ matchSizes := make (map [string ]int32 , len (matches ))
314
+ for stream , size := range matches {
315
+ matchSizes [fmt .Sprintf ("%v.%v" , stream .Subject .String (), stream .Label )] = size
316
+ }
317
+
318
+ // Results.
319
+ results := make ([]* api.Match , 0 , limit )
320
+
321
+ for _ , hit := range labelResults .Hits {
322
+ id := fmt .Sprintf ("%v.%v" , hit .ID , r .node )
323
+
324
+ // Size may be 0.
325
+ size := matchSizes [id ]
326
+
327
+ if minSize != nil && minSize .Value > size {
328
+ // Not eligible based on minimum size.
329
+ continue
330
+ }
331
+
332
+ if maxSize != nil && maxSize .Value < size {
333
+ // Not eligible based on maximum size.
334
+ continue
335
+ }
336
+
337
+ var labelString string
338
+ if l , ok := hit .Fields ["label_string" ]; ok {
339
+ if labelString , ok = l .(string ); ! ok {
340
+ r .logger .Warn ("Field not a string in match registry label cache: label_string" )
341
+ continue
342
+ }
343
+ } else {
344
+ r .logger .Warn ("Field not found in match registry label cache: label_string" )
345
+ continue
346
+ }
347
+
348
+ results = append (results , & api.Match {
349
+ MatchId : id ,
350
+ Authoritative : true ,
351
+ Label : & wrappers.StringValue {Value : labelString },
352
+ Size : size ,
353
+ })
354
+ if len (results ) == limit {
355
+ return results , nil
356
+ }
357
+ }
358
+
359
+ // We're in the query case, non-authoritative matches are not eligible so return what we can.
360
+ return results , nil
361
+ }
362
+
363
+ // It was not a query so ordering does not matter, move on to process the minimal set possible in any order.
364
+
305
365
// Match labels will only be nil if there is no label filter, no query filter, and authoritative is strictly false.
306
366
// Therefore authoritative matches will never be part of this listing at all.
307
367
var matchLabels map [uuid.UUID ]* wrappers.StringValue
0 commit comments