@@ -116,14 +116,18 @@ pub async fn list_crates(
116116 . left_join ( versions:: table. on ( default_versions:: version_id. eq ( versions:: id) ) )
117117 . select ( selection) ;
118118
119+ let pagination: PaginationOptions = PaginationOptions :: builder ( )
120+ . limit_page_numbers ( )
121+ . enable_seek ( true )
122+ . gather ( & req) ?;
123+ let is_forward = !matches ! ( pagination. page, Page :: SeekBackward ( _) ) ;
124+
119125 if let Some ( q_string) = & filter_params. q_string {
120126 if !q_string. is_empty ( ) {
121127 let q_string = q_string. as_str ( ) ;
122128
123129 let sort = sort. unwrap_or ( "relevance" ) ;
124130
125- query = query. order ( Crate :: with_name ( q_string) . desc ( ) ) ;
126-
127131 if sort == "relevance" {
128132 let q =
129133 plainto_tsquery_with_search_config ( TsConfigurationByName ( "english" ) , q_string) ;
@@ -139,7 +143,11 @@ pub async fn list_crates(
139143 default_versions:: num_versions. nullable ( ) ,
140144 ) ) ;
141145 seek = Some ( Seek :: Relevance ) ;
142- query = query. then_order_by ( rank. desc ( ) )
146+ query = if is_forward {
147+ query. order ( ( Crate :: with_name ( q_string) . desc ( ) , rank. desc ( ) ) )
148+ } else {
149+ query. order ( ( Crate :: with_name ( q_string) . asc ( ) , rank. asc ( ) ) )
150+ }
143151 } else {
144152 query = query. select ( (
145153 ALL_COLUMNS ,
@@ -152,6 +160,11 @@ pub async fn list_crates(
152160 default_versions:: num_versions. nullable ( ) ,
153161 ) ) ;
154162 seek = Some ( Seek :: Query ) ;
163+ query = if is_forward {
164+ query. order ( Crate :: with_name ( q_string) . desc ( ) )
165+ } else {
166+ query. order ( Crate :: with_name ( q_string) . asc ( ) )
167+ }
155168 }
156169 }
157170 }
@@ -163,31 +176,49 @@ pub async fn list_crates(
163176 // to ensure predictable pagination behavior.
164177 if sort == Some ( "downloads" ) {
165178 seek = Some ( Seek :: Downloads ) ;
166- query = query. order ( ( crate_downloads:: downloads. desc ( ) , crates:: id. desc ( ) ) )
179+ query = if is_forward {
180+ query. order ( ( crate_downloads:: downloads. desc ( ) , crates:: id. desc ( ) ) )
181+ } else {
182+ query. order ( ( crate_downloads:: downloads. asc ( ) , crates:: id. asc ( ) ) )
183+ } ;
167184 } else if sort == Some ( "recent-downloads" ) {
168185 seek = Some ( Seek :: RecentDownloads ) ;
169- query = query. order ( (
170- recent_crate_downloads:: downloads. desc ( ) . nulls_last ( ) ,
171- crates:: id. desc ( ) ,
172- ) )
186+ query = if is_forward {
187+ query. order ( (
188+ recent_crate_downloads:: downloads. desc ( ) . nulls_last ( ) ,
189+ crates:: id. desc ( ) ,
190+ ) )
191+ } else {
192+ query. order ( (
193+ recent_crate_downloads:: downloads. asc ( ) . nulls_first ( ) ,
194+ crates:: id. asc ( ) ,
195+ ) )
196+ } ;
173197 } else if sort == Some ( "recent-updates" ) {
174198 seek = Some ( Seek :: RecentUpdates ) ;
175- query = query. order ( ( crates:: updated_at. desc ( ) , crates:: id. desc ( ) ) ) ;
199+ query = if is_forward {
200+ query. order ( ( crates:: updated_at. desc ( ) , crates:: id. desc ( ) ) )
201+ } else {
202+ query. order ( ( crates:: updated_at. asc ( ) , crates:: id. asc ( ) ) )
203+ } ;
176204 } else if sort == Some ( "new" ) {
177205 seek = Some ( Seek :: New ) ;
178- query = query. order ( ( crates:: created_at. desc ( ) , crates:: id. desc ( ) ) ) ;
206+ query = if is_forward {
207+ query. order ( ( crates:: created_at. desc ( ) , crates:: id. desc ( ) ) )
208+ } else {
209+ query. order ( ( crates:: created_at. asc ( ) , crates:: id. asc ( ) ) )
210+ } ;
179211 } else {
180212 seek = seek. or ( Some ( Seek :: Name ) ) ;
181213 // Since the name is unique value, the inherent ordering becomes naturally unique.
182214 // Therefore, an additional auxiliary ordering column is unnecessary in this case.
183- query = query. then_order_by ( crates:: name. asc ( ) )
215+ query = if is_forward {
216+ query. then_order_by ( crates:: name. asc ( ) )
217+ } else {
218+ query. then_order_by ( crates:: name. desc ( ) )
219+ } ;
184220 }
185221
186- let pagination: PaginationOptions = PaginationOptions :: builder ( )
187- . limit_page_numbers ( )
188- . enable_seek ( true )
189- . gather ( & req) ?;
190-
191222 let explicit_page = matches ! ( pagination. page, Page :: Numeric ( _) ) ;
192223
193224 // To avoid breaking existing users, seek-based pagination is only used if an explicit page has
0 commit comments