@@ -400,42 +400,10 @@ def match_preview
400400 } , status : :unprocessable_entity
401401 end
402402
403- # Fetch PandaScore data in parallel
404- t1_data = Thread . new { @pandascore_service . fetch_team ( team1_id ) }
405- t2_data = Thread . new { @pandascore_service . fetch_team ( team2_id ) }
406- t1_recent = Thread . new { @pandascore_service . fetch_team_recent_matches ( team1_id ) }
407- t2_recent = Thread . new { @pandascore_service . fetch_team_recent_matches ( team2_id ) }
403+ team1_data , team2_data , team1_recent , team2_recent =
404+ fetch_pandascore_preview_data ( team1_id , team2_id )
408405
409- team1_data = t1_data . value
410- team2_data = t2_data . value
411- team1_recent = t1_recent . value
412- team2_recent = t2_recent . value
413-
414- # H2H stats from Elasticsearch
415- must_clauses = [
416- {
417- bool : {
418- should : [
419- { bool : { must : [ team_clause ( team1_name , 'team1' ) , team_clause ( team2_name , 'team2' ) ] } } ,
420- { bool : { must : [ team_clause ( team2_name , 'team1' ) , team_clause ( team1_name , 'team2' ) ] } }
421- ] ,
422- minimum_should_match : 1
423- }
424- }
425- ]
426-
427- es_body = {
428- query : { bool : { must : must_clauses } } ,
429- size : 0 ,
430- aggs : {
431- team1_wins : { filter : win_team_clause ( team1_name ) } ,
432- team2_wins : { filter : win_team_clause ( team2_name ) }
433- }
434- }
435-
436- es_result = ElasticsearchClient . new . search ( index : 'lol_pro_matches' , body : es_body )
437- h2h_wins_t1 = es_result . dig ( 'aggregations' , 'team1_wins' , 'doc_count' ) || 0
438- h2h_wins_t2 = es_result . dig ( 'aggregations' , 'team2_wins' , 'doc_count' ) || 0
406+ h2h_wins_t1 , h2h_wins_t2 = fetch_h2h_wins ( team1_name , team2_name )
439407
440408 render json : {
441409 data : {
@@ -462,32 +430,9 @@ def es_series
462430
463431 raise ArgumentError , 'team1 and team2 are required' if team1 . blank? || team2 . blank?
464432
465- must_clauses = [
466- {
467- bool : {
468- should : [
469- { bool : { must : [ team_clause ( team1 , 'team1' ) , team_clause ( team2 , 'team2' ) ] } } ,
470- { bool : { must : [ team_clause ( team2 , 'team1' ) , team_clause ( team1 , 'team2' ) ] } }
471- ] ,
472- minimum_should_match : 1
473- }
474- }
475- ]
476-
477- if params [ :after ] . present? && params [ :before ] . present?
478- must_clauses << {
479- range : { start_time : { gte : params [ :after ] , lte : params [ :before ] } }
480- }
481- end
482-
483- es_body = {
484- query : { bool : { must : must_clauses } } ,
485- sort : [ { start_time : { order : 'desc' } } ] ,
486- size : limit
487- }
488-
489- result = ElasticsearchClient . new . search ( index : 'lol_pro_matches' , body : es_body )
490- games = result . dig ( 'hits' , 'hits' ) &.map { |h | h [ '_source' ] } || [ ]
433+ es_body = build_series_query ( team1 , team2 , limit )
434+ result = ElasticsearchClient . new . search ( index : 'lol_pro_matches' , body : es_body )
435+ games = result . dig ( 'hits' , 'hits' ) &.map { |h | h [ '_source' ] } || [ ]
491436
492437 render json : { data : { games : games , total : games . size } }
493438 rescue ArgumentError => e
@@ -504,6 +449,52 @@ def set_pandascore_service
504449 @pandascore_service = PandascoreService . instance
505450 end
506451
452+ def fetch_pandascore_preview_data ( team1_id , team2_id )
453+ t1_data = Thread . new { @pandascore_service . fetch_team ( team1_id ) }
454+ t2_data = Thread . new { @pandascore_service . fetch_team ( team2_id ) }
455+ t1_recent = Thread . new { @pandascore_service . fetch_team_recent_matches ( team1_id ) }
456+ t2_recent = Thread . new { @pandascore_service . fetch_team_recent_matches ( team2_id ) }
457+ [ t1_data . value , t2_data . value , t1_recent . value , t2_recent . value ]
458+ end
459+
460+ def fetch_h2h_wins ( team1_name , team2_name )
461+ must_clauses = [ h2h_matchup_clause ( team1_name , team2_name ) ]
462+ es_body = {
463+ query : { bool : { must : must_clauses } } ,
464+ size : 0 ,
465+ aggs : {
466+ team1_wins : { filter : win_team_clause ( team1_name ) } ,
467+ team2_wins : { filter : win_team_clause ( team2_name ) }
468+ }
469+ }
470+ result = ElasticsearchClient . new . search ( index : 'lol_pro_matches' , body : es_body )
471+ wins_t1 = result . dig ( 'aggregations' , 'team1_wins' , 'doc_count' ) || 0
472+ wins_t2 = result . dig ( 'aggregations' , 'team2_wins' , 'doc_count' ) || 0
473+ [ wins_t1 , wins_t2 ]
474+ end
475+
476+ def h2h_matchup_clause ( team1_name , team2_name )
477+ {
478+ bool : {
479+ should : [
480+ { bool : { must : [ team_clause ( team1_name , 'team1' ) , team_clause ( team2_name , 'team2' ) ] } } ,
481+ { bool : { must : [ team_clause ( team2_name , 'team1' ) , team_clause ( team1_name , 'team2' ) ] } }
482+ ] ,
483+ minimum_should_match : 1
484+ }
485+ }
486+ end
487+
488+ def build_series_query ( team1 , team2 , limit )
489+ must_clauses = [ h2h_matchup_clause ( team1 , team2 ) ]
490+ must_clauses << { range : { start_time : { gte : params [ :after ] , lte : params [ :before ] } } } if date_filter?
491+ { query : { bool : { must : must_clauses } } , sort : [ { start_time : { order : 'desc' } } ] , size : limit }
492+ end
493+
494+ def date_filter?
495+ params [ :after ] . present? && params [ :before ] . present?
496+ end
497+
507498 # Builds an ES should clause that matches a team name using:
508499 # 1. Exact term match (handles perfect name equality)
509500 # 2. Prefix wildcard on first word, case-insensitive (handles suffix differences
0 commit comments