@@ -1529,6 +1529,72 @@ mod tests {
1529
1529
Ok ( ( ) )
1530
1530
}
1531
1531
1532
+ proptest ! {
1533
+ #[ test]
1534
+ fn test_top_field_collect_string_prop(
1535
+ order in prop_oneof!( Just ( Order :: Desc ) , Just ( Order :: Asc ) ) ,
1536
+ limit in 1 ..256_usize ,
1537
+ offset in 0 ..256_usize ,
1538
+ segments_terms in
1539
+ proptest:: collection:: vec(
1540
+ proptest:: collection:: vec( 0 ..32_u8 , 1 ..32_usize ) ,
1541
+ 0 ..8_usize ,
1542
+ )
1543
+ ) {
1544
+ let mut schema_builder = Schema :: builder( ) ;
1545
+ let city = schema_builder. add_text_field( "city" , TEXT | FAST ) ;
1546
+ let schema = schema_builder. build( ) ;
1547
+ let index = Index :: create_in_ram( schema) ;
1548
+ let mut index_writer = index. writer_for_tests( ) ?;
1549
+
1550
+ // A Vec<Vec<u8>>, where the outer Vec represents segments, and the inner Vec
1551
+ // represents terms.
1552
+ for segment_terms in segments_terms. into_iter( ) {
1553
+ for term in segment_terms. into_iter( ) {
1554
+ let term = format!( "{term:0>3}" ) ;
1555
+ index_writer. add_document( doc!(
1556
+ city => term,
1557
+ ) ) ?;
1558
+ }
1559
+ index_writer. commit( ) ?;
1560
+ }
1561
+
1562
+ let searcher = index. reader( ) ?. searcher( ) ;
1563
+ let top_n_results = searcher. search( & AllQuery , & TopDocs :: with_limit( limit)
1564
+ . and_offset( offset)
1565
+ . order_by_string_fast_field( "city" , order. clone( ) ) ) ?;
1566
+ let all_results = searcher. search( & AllQuery , & DocSetCollector ) ?. into_iter( ) . map( |doc_address| {
1567
+ // Get the term for this address.
1568
+ // NOTE: We can't determine the SegmentIds that will be generated for Segments
1569
+ // ahead of time, so we can't pre-compute the expected `DocAddress`es.
1570
+ let column = searcher. segment_readers( ) [ doc_address. segment_ord as usize ] . fast_fields( ) . str ( "city" ) . unwrap( ) . unwrap( ) ;
1571
+ let term_ord = column. term_ords( doc_address. doc_id) . next( ) . unwrap( ) ;
1572
+ let mut city = Vec :: new( ) ;
1573
+ column. dictionary( ) . ord_to_term( term_ord, & mut city) . unwrap( ) ;
1574
+ ( String :: try_from( city) . unwrap( ) , doc_address)
1575
+ } ) ;
1576
+
1577
+ // Using the TopDocs collector should always be equivalent to sorting, skipping the
1578
+ // offset, and then taking the limit.
1579
+ let sorted_docs: Vec <_> = if order. is_desc( ) {
1580
+ let mut comparable_docs: Vec <ComparableDoc <_, _, true >> =
1581
+ all_results. into_iter( ) . map( |( feature, doc) | ComparableDoc { feature, doc} ) . collect( ) ;
1582
+ comparable_docs. sort( ) ;
1583
+ comparable_docs. into_iter( ) . map( |cd| ( cd. feature, cd. doc) ) . collect( )
1584
+ } else {
1585
+ let mut comparable_docs: Vec <ComparableDoc <_, _, false >> =
1586
+ all_results. into_iter( ) . map( |( feature, doc) | ComparableDoc { feature, doc} ) . collect( ) ;
1587
+ comparable_docs. sort( ) ;
1588
+ comparable_docs. into_iter( ) . map( |cd| ( cd. feature, cd. doc) ) . collect( )
1589
+ } ;
1590
+ let expected_docs = sorted_docs. into_iter( ) . skip( offset) . take( limit) . collect:: <Vec <_>>( ) ;
1591
+ prop_assert_eq!(
1592
+ expected_docs,
1593
+ top_n_results
1594
+ ) ;
1595
+ }
1596
+ }
1597
+
1532
1598
#[ test]
1533
1599
#[ should_panic]
1534
1600
fn test_field_does_not_exist ( ) {
0 commit comments