@@ -288,7 +288,6 @@ public void Phrase()
288288 {
289289 // This test case exercises the indexName and returnStoredSource arguments. The
290290 // remaining test cases omit them.
291- var coll = GetTestCollection ( ) ;
292291 var results = GetTestCollection ( ) . Aggregate ( )
293292 . Search ( Builders . Search . Phrase ( x => x . Body , "life, liberty, and the pursuit of happiness" ) ,
294293 new SearchHighlightOptions < HistoricalDocument > ( x => x . Body ) ,
@@ -381,6 +380,78 @@ public void Range()
381380 results . Should ( ) . ContainSingle ( ) . Which . Name . Should ( ) . Be ( "House close to station & direct to opera house...." ) ;
382381 }
383382
383+ [ Fact ]
384+ public void SearchSequenceToken ( )
385+ {
386+ const int limitVal = 10 ;
387+ var titles = new [ ]
388+ {
389+ "Equinox Flower" ,
390+ "Flower Drum Song" ,
391+ "Cactus Flower" ,
392+ "The Flower of My Secret" ,
393+ } ;
394+
395+ var searchDefinition = Builders < Movie > . Search . Text ( t => t . Title , "flower" ) ;
396+ var searchOptions = new SearchOptions < Movie >
397+ {
398+ IndexName = "default" ,
399+ Sort = Builders < Movie > . Sort . Ascending ( "year" )
400+ } ;
401+ var projection = Builders < Movie > . Projection
402+ . Include ( x => x . Title )
403+ . MetaSearchSequenceToken ( x => x . PaginationToken ) ;
404+
405+ // Base search
406+ var baseSearchResults = GetSynonymTestCollection ( )
407+ . Aggregate ( )
408+ . Search ( searchDefinition , searchOptions )
409+ . Project < Movie > ( projection )
410+ . Limit ( limitVal )
411+ . ToList ( ) ;
412+
413+ baseSearchResults . Count . Should ( ) . Be ( limitVal ) ;
414+ baseSearchResults . ForEach ( m => m . PaginationToken . Should ( ) . NotBeNullOrEmpty ( ) ) ;
415+ baseSearchResults [ 0 ] . Title . Should ( ) . Be ( titles [ 0 ] ) ;
416+ baseSearchResults [ 1 ] . Title . Should ( ) . Be ( titles [ 1 ] ) ;
417+ baseSearchResults [ 2 ] . Title . Should ( ) . Be ( titles [ 2 ] ) ;
418+ baseSearchResults [ 3 ] . Title . Should ( ) . Be ( titles [ 3 ] ) ;
419+
420+ // Testing SearchAfter
421+ // We're searching after the 2nd result of the base search
422+ searchOptions . SearchAfter = baseSearchResults [ 1 ] . PaginationToken ;
423+ var searchAfterResults = GetSynonymTestCollection ( )
424+ . Aggregate ( )
425+ . Search ( searchDefinition , searchOptions )
426+ . Project < Movie > ( projection )
427+ . Limit ( limitVal )
428+ . ToList ( ) ;
429+
430+ searchAfterResults . Count . Should ( ) . Be ( limitVal ) ;
431+ searchAfterResults . ForEach ( m => m . PaginationToken . Should ( ) . NotBeNullOrEmpty ( ) ) ;
432+ searchAfterResults [ 0 ] . Title . Should ( ) . Be ( titles [ 2 ] ) ;
433+ searchAfterResults [ 1 ] . Title . Should ( ) . Be ( titles [ 3 ] ) ;
434+
435+ // Testing SearchBefore
436+ // We're searching before the 4th result of the base search
437+ searchOptions . SearchAfter = null ;
438+ searchOptions . SearchBefore = baseSearchResults [ 3 ] . PaginationToken ;
439+ var searchBeforeResults = GetSynonymTestCollection ( )
440+ . Aggregate ( )
441+ . Search ( searchDefinition , searchOptions )
442+ . Project < Movie > ( projection )
443+ . Limit ( limitVal )
444+ . ToList ( ) ;
445+
446+ // We only get the first 3 elements of the base search
447+ searchBeforeResults . Count . Should ( ) . Be ( 3 ) ;
448+ searchBeforeResults . ForEach ( m => m . PaginationToken . Should ( ) . NotBeNullOrEmpty ( ) ) ;
449+ // With searchBefore the results are reversed
450+ searchBeforeResults [ 0 ] . Title . Should ( ) . Be ( titles [ 2 ] ) ;
451+ searchBeforeResults [ 1 ] . Title . Should ( ) . Be ( titles [ 1 ] ) ;
452+ searchBeforeResults [ 2 ] . Title . Should ( ) . Be ( titles [ 0 ] ) ;
453+ }
454+
384455 [ Fact ]
385456 public void Search_count_lowerBound ( )
386457 {
@@ -686,6 +757,9 @@ public class Movie
686757
687758 [ BsonElement ( "score" ) ]
688759 public double Score { get ; set ; }
760+
761+ [ BsonElement ( "paginationToken" ) ]
762+ public string PaginationToken { get ; set ; }
689763 }
690764
691765 [ BsonIgnoreExtraElements ]
0 commit comments