@@ -163,16 +163,16 @@ func (i *indexAliasImpl) SearchInContext(ctx context.Context, req *SearchRequest
163163 return nil , ErrorAliasEmpty
164164 }
165165 if _ , ok := ctx .Value (search .PreSearchKey ).(bool ); ok {
166- // since presearchKey is set, it means that the request
167- // is being executed as part of a presearch , which
166+ // since preSearchKey is set, it means that the request
167+ // is being executed as part of a preSearch , which
168168 // indicates that this index alias is set as an Index
169- // in another alias, so we need to do a presearch search
169+ // in another alias, so we need to do a preSearch search
170170 // and NOT a real search
171171 return preSearchDataSearch (ctx , req , i .indexes ... )
172172 }
173173
174174 // at this point we know we are doing a real search
175- // either after a presearch is done, or directly
175+ // either after a preSearch is done, or directly
176176 // on the alias
177177
178178 // check if request has preSearchData which would indicate that the
@@ -203,9 +203,9 @@ func (i *indexAliasImpl) SearchInContext(ctx context.Context, req *SearchRequest
203203 // check if preSearchData needs to be gathered from all indexes
204204 // before executing the query
205205 var err error
206- // only perform presearch if
206+ // only perform preSearch if
207207 // - the request does not already have preSearchData
208- // - the request requires presearch
208+ // - the request requires preSearch
209209 var preSearchDuration time.Duration
210210 var sr * SearchResult
211211 if req .PreSearchData == nil && preSearchRequired (req ) {
@@ -214,15 +214,19 @@ func (i *indexAliasImpl) SearchInContext(ctx context.Context, req *SearchRequest
214214 if err != nil {
215215 return nil , err
216216 }
217- // check if the presearch result has any errors and if so
217+ // check if the preSearch result has any errors and if so
218218 // return the search result as is without executing the query
219219 // so that the errors are not lost
220- if preSearchResult .Status .Failed > 0 {
220+ if preSearchResult .Status .Failed > 0 || len ( preSearchResult . Status . Errors ) > 0 {
221221 return preSearchResult , nil
222222 }
223+ // finalize the preSearch result now
224+ finalizePreSearchResult (req , preSearchResult )
223225
224- // if there are no errors, then merge the data in the presearch result
225- preSearchResult = mergePreSearchResult (req , preSearchResult , i .indexes )
226+ // if there are no errors, then merge the data in the preSearch result
227+ // and construct the preSearchData to be used in the actual search
228+ // if the request is satisfied by the preSearch result, then we can
229+ // directly return the preSearch result as the final result
226230 if requestSatisfiedByPreSearch (req ) {
227231 sr = finalizeSearchResult (req , preSearchResult )
228232 // no need to run the 2nd phase MultiSearch(..)
@@ -235,7 +239,7 @@ func (i *indexAliasImpl) SearchInContext(ctx context.Context, req *SearchRequest
235239 preSearchDuration = time .Since (searchStart )
236240 }
237241
238- // check if search result was generated as part of presearch itself
242+ // check if search result was generated as part of preSearch itself
239243 if sr == nil {
240244 sr , err = MultiSearch (ctx , req , preSearchData , i .indexes ... )
241245 if err != nil {
@@ -533,13 +537,7 @@ func preSearch(ctx context.Context, req *SearchRequest, indexes ...Index) (*Sear
533537 return preSearchDataSearch (newCtx , dummyRequest , indexes ... )
534538}
535539
536- func tagHitsWithIndexName (sr * SearchResult , indexName string ) {
537- for _ , hit := range sr .Hits {
538- hit .IndexNames = append (hit .IndexNames , indexName )
539- }
540- }
541-
542- // if the request is satisfied by just the presearch result,
540+ // if the request is satisfied by just the preSearch result,
543541// finalize the result and return it directly without
544542// performing multi search
545543func finalizeSearchResult (req * SearchRequest , preSearchResult * SearchResult ) * SearchResult {
@@ -551,7 +549,7 @@ func finalizeSearchResult(req *SearchRequest, preSearchResult *SearchResult) *Se
551549 preSearchResult .Total = uint64 (preSearchResult .Hits .Len ())
552550 maxScore := float64 (0 )
553551 for i , hit := range preSearchResult .Hits {
554- // since we are now using the presearch result as the final result
552+ // since we are now using the preSearch result as the final result
555553 // we can discard the indexNames from the hits as they are no longer
556554 // relevant.
557555 hit .IndexNames = nil
@@ -587,14 +585,6 @@ func finalizeSearchResult(req *SearchRequest, preSearchResult *SearchResult) *Se
587585 return preSearchResult
588586}
589587
590- func mergePreSearchResult (req * SearchRequest , res * SearchResult ,
591- indexes []Index ) * SearchResult {
592- if requestHasKNN (req ) {
593- res .Hits = mergeKNNDocumentMatches (req , res .Hits )
594- }
595- return res
596- }
597-
598588func requestSatisfiedByPreSearch (req * SearchRequest ) bool {
599589 if requestHasKNN (req ) && isKNNrequestSatisfiedByPreSearch (req ) {
600590 return true
@@ -609,7 +599,7 @@ func constructPreSearchData(req *SearchRequest, preSearchResult *SearchResult, i
609599 }
610600 var err error
611601 if requestHasKNN (req ) {
612- mergedOut , err = constructKnnPresearchData (mergedOut , preSearchResult , indexes )
602+ mergedOut , err = constructKnnPreSearchData (mergedOut , preSearchResult , indexes )
613603 if err != nil {
614604 return nil , err
615605 }
@@ -619,50 +609,53 @@ func constructPreSearchData(req *SearchRequest, preSearchResult *SearchResult, i
619609
620610func preSearchDataSearch (ctx context.Context , req * SearchRequest , indexes ... Index ) (* SearchResult , error ) {
621611 asyncResults := make (chan * asyncSearchResult , len (indexes ))
622-
623612 // run search on each index in separate go routine
624613 var waitGroup sync.WaitGroup
625-
626614 var searchChildIndex = func (in Index , childReq * SearchRequest ) {
627615 rv := asyncSearchResult {Name : in .Name ()}
628616 rv .Result , rv .Err = in .SearchInContext (ctx , childReq )
629617 asyncResults <- & rv
630618 waitGroup .Done ()
631619 }
632-
633620 waitGroup .Add (len (indexes ))
634621 for _ , in := range indexes {
635622 go searchChildIndex (in , createChildSearchRequest (req , nil ))
636623 }
637-
638624 // on another go routine, close after finished
639625 go func () {
640626 waitGroup .Wait ()
641627 close (asyncResults )
642628 }()
643-
629+ // the final search result to be returned after combining the preSearch results
644630 var sr * SearchResult
631+ // the preSearch result processor
632+ var prp preSearchResultProcessor
633+ // error map
645634 indexErrors := make (map [string ]error )
646-
647635 for asr := range asyncResults {
648636 if asr .Err == nil {
637+ // a valid preSearch result
638+ if prp == nil {
639+ // first valid preSearch result
640+ // create a new preSearch result processor
641+ prp = createPreSearchResultProcessor (req )
642+ }
643+ prp .add (asr .Result , asr .Name )
649644 if sr == nil {
650645 // first result
651- sr = asr .Result
652- tagHitsWithIndexName (sr , asr .Name )
646+ sr = & SearchResult {
647+ Status : asr .Result .Status ,
648+ Cost : asr .Result .Cost ,
649+ }
653650 } else {
654651 // merge with previous
655- tagHitsWithIndexName (asr .Result , asr . Name )
656- sr .Merge ( asr .Result )
652+ sr . Status . Merge (asr .Result . Status )
653+ sr .Cost += asr .Result . Cost
657654 }
658655 } else {
659656 indexErrors [asr .Name ] = asr .Err
660657 }
661658 }
662-
663- // merge just concatenated all the hits
664- // now lets clean it up
665-
666659 // handle case where no results were successful
667660 if sr == nil {
668661 sr = & SearchResult {
@@ -671,16 +664,12 @@ func preSearchDataSearch(ctx context.Context, req *SearchRequest, indexes ...Ind
671664 },
672665 }
673666 }
674-
675- // in presearch partial results are not allowed as it can lead to
667+ // in preSearch, partial results are not allowed as it can lead to
676668 // the real search giving incorrect results, and hence the search
677- // result is reset.
678- // discard partial hits if some child index has failed or
679- // if some child alias has returned partial results.
669+ // result is not populated with any of the processed data from
670+ // the preSearch result processor if there are any errors
671+ // or the preSearch result status has any failures
680672 if len (indexErrors ) > 0 || sr .Status .Failed > 0 {
681- sr = & SearchResult {
682- Status : sr .Status ,
683- }
684673 if sr .Status .Errors == nil {
685674 sr .Status .Errors = make (map [string ]error )
686675 }
@@ -689,8 +678,9 @@ func preSearchDataSearch(ctx context.Context, req *SearchRequest, indexes ...Ind
689678 sr .Status .Total ++
690679 sr .Status .Failed ++
691680 }
681+ } else {
682+ prp .finalize (sr )
692683 }
693-
694684 return sr , nil
695685}
696686
0 commit comments