@@ -142,6 +142,260 @@ func (struts *SearchReduceUtilTestSuite) TestReduceSearchResult() {
142142 }
143143}
144144
145+ // TestReduceWithEmptyFieldsData tests reduce functions when FieldsData is empty (requery scenario)
146+ func (struts * SearchReduceUtilTestSuite ) TestReduceWithEmptyFieldsData () {
147+ ctx := context .Background ()
148+ nq := int64 (1 )
149+ topK := int64 (5 )
150+ offset := int64 (0 )
151+
152+ // Create search results with empty FieldsData (simulating requery scenario)
153+ searchResultData1 := & schemapb.SearchResultData {
154+ Ids : & schemapb.IDs {
155+ IdField : & schemapb.IDs_IntId {
156+ IntId : & schemapb.LongArray {
157+ Data : []int64 {1 , 2 , 3 , 4 , 5 },
158+ },
159+ },
160+ },
161+ Scores : []float32 {0.9 , 0.8 , 0.7 , 0.6 , 0.5 },
162+ Topks : []int64 {5 },
163+ NumQueries : nq ,
164+ TopK : topK ,
165+ FieldsData : []* schemapb.FieldData {}, // Empty FieldsData for requery
166+ }
167+
168+ searchResultData2 := & schemapb.SearchResultData {
169+ Ids : & schemapb.IDs {
170+ IdField : & schemapb.IDs_IntId {
171+ IntId : & schemapb.LongArray {
172+ Data : []int64 {6 , 7 , 8 , 9 , 10 },
173+ },
174+ },
175+ },
176+ Scores : []float32 {0.85 , 0.75 , 0.65 , 0.55 , 0.45 },
177+ Topks : []int64 {5 },
178+ NumQueries : nq ,
179+ TopK : topK ,
180+ FieldsData : []* schemapb.FieldData {}, // Empty FieldsData for requery
181+ }
182+
183+ // Test reduceSearchResultDataNoGroupBy with empty FieldsData
184+ {
185+ results , err := reduceSearchResultDataNoGroupBy (ctx , []* schemapb.SearchResultData {searchResultData1 , searchResultData2 }, nq , topK , "L2" , schemapb .DataType_Int64 , offset )
186+ struts .NoError (err )
187+ struts .NotNil (results )
188+ // Should have merged results without panic
189+ struts .Equal (int64 (5 ), results .Results .Topks [0 ])
190+ // FieldsData should be empty since all inputs were empty
191+ struts .Equal (0 , len (results .Results .FieldsData ))
192+ }
193+
194+ // Test reduceSearchResultDataWithGroupBy with empty FieldsData
195+ {
196+ // Add GroupByFieldValue to support group by
197+ searchResultData1 .GroupByFieldValue = & schemapb.FieldData {
198+ Type : schemapb .DataType_VarChar ,
199+ FieldName : "group" ,
200+ FieldId : 101 ,
201+ Field : & schemapb.FieldData_Scalars {
202+ Scalars : & schemapb.ScalarField {
203+ Data : & schemapb.ScalarField_StringData {
204+ StringData : & schemapb.StringArray {
205+ Data : []string {"a" , "b" , "c" , "a" , "b" },
206+ },
207+ },
208+ },
209+ },
210+ }
211+ searchResultData2 .GroupByFieldValue = & schemapb.FieldData {
212+ Type : schemapb .DataType_VarChar ,
213+ FieldName : "group" ,
214+ FieldId : 101 ,
215+ Field : & schemapb.FieldData_Scalars {
216+ Scalars : & schemapb.ScalarField {
217+ Data : & schemapb.ScalarField_StringData {
218+ StringData : & schemapb.StringArray {
219+ Data : []string {"c" , "a" , "b" , "c" , "a" },
220+ },
221+ },
222+ },
223+ },
224+ }
225+
226+ results , err := reduceSearchResultDataWithGroupBy (ctx , []* schemapb.SearchResultData {searchResultData1 , searchResultData2 }, nq , topK , "L2" , schemapb .DataType_Int64 , offset , int64 (2 ))
227+ struts .NoError (err )
228+ struts .NotNil (results )
229+ // FieldsData should be empty since all inputs were empty
230+ struts .Equal (0 , len (results .Results .FieldsData ))
231+ }
232+
233+ // Test reduceAdvanceGroupBY with empty FieldsData
234+ {
235+ results , err := reduceAdvanceGroupBY (ctx , []* schemapb.SearchResultData {searchResultData1 , searchResultData2 }, nq , topK , schemapb .DataType_Int64 , "L2" )
236+ struts .NoError (err )
237+ struts .NotNil (results )
238+ // FieldsData should be empty since all inputs were empty
239+ struts .Equal (0 , len (results .Results .FieldsData ))
240+ }
241+ }
242+
243+ // TestReduceWithPartialEmptyFieldsData tests when first result has empty FieldsData but second has data
244+ func (struts * SearchReduceUtilTestSuite ) TestReduceWithPartialEmptyFieldsData () {
245+ ctx := context .Background ()
246+ nq := int64 (1 )
247+ topK := int64 (3 )
248+ offset := int64 (0 )
249+
250+ // First result with empty FieldsData
251+ searchResultData1 := & schemapb.SearchResultData {
252+ Ids : & schemapb.IDs {
253+ IdField : & schemapb.IDs_IntId {
254+ IntId : & schemapb.LongArray {
255+ Data : []int64 {1 , 2 , 3 },
256+ },
257+ },
258+ },
259+ Scores : []float32 {0.9 , 0.8 , 0.7 },
260+ Topks : []int64 {3 },
261+ NumQueries : nq ,
262+ TopK : topK ,
263+ FieldsData : []* schemapb.FieldData {}, // Empty
264+ }
265+
266+ // Second result with non-empty FieldsData
267+ searchResultData2 := & schemapb.SearchResultData {
268+ Ids : & schemapb.IDs {
269+ IdField : & schemapb.IDs_IntId {
270+ IntId : & schemapb.LongArray {
271+ Data : []int64 {4 , 5 , 6 },
272+ },
273+ },
274+ },
275+ Scores : []float32 {0.85 , 0.75 , 0.65 },
276+ Topks : []int64 {3 },
277+ NumQueries : nq ,
278+ TopK : topK ,
279+ FieldsData : []* schemapb.FieldData {
280+ {
281+ Type : schemapb .DataType_Int64 ,
282+ FieldName : "field1" ,
283+ FieldId : 100 ,
284+ Field : & schemapb.FieldData_Scalars {
285+ Scalars : & schemapb.ScalarField {
286+ Data : & schemapb.ScalarField_LongData {
287+ LongData : & schemapb.LongArray {
288+ Data : []int64 {40 , 50 , 60 },
289+ },
290+ },
291+ },
292+ },
293+ },
294+ },
295+ }
296+
297+ // Test: Should use the non-empty FieldsData from second result
298+ results , err := reduceSearchResultDataNoGroupBy (ctx , []* schemapb.SearchResultData {searchResultData1 , searchResultData2 }, nq , topK , "L2" , schemapb .DataType_Int64 , offset )
299+ struts .NoError (err )
300+ struts .NotNil (results )
301+ // Should have initialized FieldsData from second result
302+ struts .Greater (len (results .Results .FieldsData ), 0 )
303+ }
304+
305+ // TestRankWithEmptyFieldsData tests rank functions when FieldsData is empty
306+ func (struts * SearchReduceUtilTestSuite ) TestRankWithEmptyFieldsData () {
307+ ctx := context .Background ()
308+ nq := int64 (1 )
309+ limit := int64 (3 )
310+ offset := int64 (0 )
311+ roundDecimal := int64 (- 1 )
312+ rankParams := & rankParams {limit : limit , offset : offset , roundDecimal : roundDecimal }
313+
314+ // Create search results with empty FieldsData
315+ searchResult1 := & milvuspb.SearchResults {
316+ Results : & schemapb.SearchResultData {
317+ Ids : & schemapb.IDs {
318+ IdField : & schemapb.IDs_IntId {
319+ IntId : & schemapb.LongArray {
320+ Data : []int64 {1 , 2 , 3 },
321+ },
322+ },
323+ },
324+ Scores : []float32 {0.9 , 0.8 , 0.7 },
325+ Topks : []int64 {3 },
326+ NumQueries : nq ,
327+ FieldsData : []* schemapb.FieldData {}, // Empty
328+ },
329+ }
330+
331+ searchResult2 := & milvuspb.SearchResults {
332+ Results : & schemapb.SearchResultData {
333+ Ids : & schemapb.IDs {
334+ IdField : & schemapb.IDs_IntId {
335+ IntId : & schemapb.LongArray {
336+ Data : []int64 {2 , 4 , 5 },
337+ },
338+ },
339+ },
340+ Scores : []float32 {0.85 , 0.75 , 0.65 },
341+ Topks : []int64 {3 },
342+ NumQueries : nq ,
343+ FieldsData : []* schemapb.FieldData {}, // Empty
344+ },
345+ }
346+
347+ searchResults := []* milvuspb.SearchResults {searchResult1 , searchResult2 }
348+
349+ // Test rankSearchResultDataByPk with empty FieldsData
350+ {
351+ results , err := rankSearchResultDataByPk (ctx , nq , rankParams , schemapb .DataType_Int64 , searchResults )
352+ struts .NoError (err )
353+ struts .NotNil (results )
354+ // FieldsData should be empty since all inputs were empty
355+ struts .Equal (0 , len (results .Results .FieldsData ))
356+ }
357+
358+ // Test rankSearchResultDataByGroup with empty FieldsData
359+ {
360+ // Add group by values
361+ searchResult1 .Results .GroupByFieldValue = & schemapb.FieldData {
362+ Type : schemapb .DataType_VarChar ,
363+ FieldName : "group" ,
364+ FieldId : 101 ,
365+ Field : & schemapb.FieldData_Scalars {
366+ Scalars : & schemapb.ScalarField {
367+ Data : & schemapb.ScalarField_StringData {
368+ StringData : & schemapb.StringArray {
369+ Data : []string {"a" , "b" , "c" },
370+ },
371+ },
372+ },
373+ },
374+ }
375+ searchResult2 .Results .GroupByFieldValue = & schemapb.FieldData {
376+ Type : schemapb .DataType_VarChar ,
377+ FieldName : "group" ,
378+ FieldId : 101 ,
379+ Field : & schemapb.FieldData_Scalars {
380+ Scalars : & schemapb.ScalarField {
381+ Data : & schemapb.ScalarField_StringData {
382+ StringData : & schemapb.StringArray {
383+ Data : []string {"b" , "a" , "c" },
384+ },
385+ },
386+ },
387+ },
388+ }
389+
390+ groupScorer , _ := GetGroupScorer ("max" )
391+ results , err := rankSearchResultDataByGroup (ctx , nq , rankParams , schemapb .DataType_Int64 , searchResults , groupScorer , int64 (2 ))
392+ struts .NoError (err )
393+ struts .NotNil (results )
394+ // FieldsData should be empty since all inputs were empty
395+ struts .Equal (0 , len (results .Results .FieldsData ))
396+ }
397+ }
398+
145399func TestSearchReduceUtilTestSuite (t * testing.T ) {
146400 suite .Run (t , new (SearchReduceUtilTestSuite ))
147401}
0 commit comments