@@ -5,7 +5,7 @@ use diesel_full_text_search::*;
5
5
use controllers:: helpers:: Paginate ;
6
6
use controllers:: prelude:: * ;
7
7
use views:: EncodableCrate ;
8
- use models:: { Badge , Crate , OwnerKind , Version } ;
8
+ use models:: { Crate , CrateBadge , OwnerKind , Version } ;
9
9
use schema:: * ;
10
10
11
11
use models:: krate:: { canon_crate_name, ALL_COLUMNS } ;
@@ -147,50 +147,47 @@ pub fn search(req: &mut Request) -> CargoResult<Response> {
147
147
query = query. then_order_by ( crates:: name. asc ( ) )
148
148
}
149
149
150
- // The database query returns a tuple within a tuple , with the root
150
+ // The database query returns a tuple within a tuple, with the root
151
151
// tuple containing 3 items.
152
152
let data = query
153
153
. paginate ( limit, offset)
154
154
. load :: < ( ( Crate , bool , Option < i64 > ) , i64 ) > ( & * conn) ?;
155
155
let total = data. first ( ) . map ( |& ( _, t) | t) . unwrap_or ( 0 ) ;
156
- let crates = data. iter ( )
157
- . map ( |& ( ( ref c, _, _) , _) | c. clone ( ) )
158
- . collect :: < Vec < _ > > ( ) ;
159
- let perfect_matches = data. clone ( )
160
- . into_iter ( )
161
- . map ( |( ( _, b, _) , _) | b)
162
- . collect :: < Vec < _ > > ( ) ;
163
- let recent_downloads = data. clone ( )
164
- . into_iter ( )
165
- . map ( |( ( _, _, s) , _) | s. unwrap_or ( 0 ) )
156
+ let perfect_matches = data. iter ( ) . map ( |& ( ( _, b, _) , _) | b) . collect :: < Vec < _ > > ( ) ;
157
+ let recent_downloads = data. iter ( )
158
+ . map ( |& ( ( _, _, s) , _) | s. unwrap_or ( 0 ) )
166
159
. collect :: < Vec < _ > > ( ) ;
160
+ let crates = data. into_iter ( ) . map ( |( ( c, _, _) , _) | c) . collect :: < Vec < _ > > ( ) ;
167
161
168
162
let versions = Version :: belonging_to ( & crates)
169
163
. load :: < Version > ( & * conn) ?
170
164
. grouped_by ( & crates)
171
165
. into_iter ( )
172
166
. map ( |versions| Version :: max ( versions. into_iter ( ) . map ( |v| v. num ) ) ) ;
173
167
168
+ let badges = CrateBadge :: belonging_to ( & crates)
169
+ . select ( ( badges:: crate_id, badges:: all_columns) )
170
+ . load :: < CrateBadge > ( & conn) ?
171
+ . grouped_by ( & crates)
172
+ . into_iter ( )
173
+ . map ( |badges| badges. into_iter ( ) . map ( |cb| cb. badge ) . collect ( ) ) ;
174
+
174
175
let crates = versions
175
176
. zip ( crates)
176
177
. zip ( perfect_matches)
177
178
. zip ( recent_downloads)
179
+ . zip ( badges)
178
180
. map (
179
- |( ( ( max_version, krate) , perfect_match) , recent_downloads) | {
180
- // FIXME: If we add crate_id to the Badge enum we can eliminate
181
- // this N+1
182
- let badges = badges:: table
183
- . filter ( badges:: crate_id. eq ( krate. id ) )
184
- . load :: < Badge > ( & * conn) ?;
185
- Ok ( krate. minimal_encodable (
181
+ |( ( ( ( max_version, krate) , perfect_match) , recent_downloads) , badges) | {
182
+ krate. minimal_encodable (
186
183
& max_version,
187
184
Some ( badges) ,
188
185
perfect_match,
189
186
Some ( recent_downloads) ,
190
- ) )
187
+ )
191
188
} ,
192
189
)
193
- . collect :: < Result < _ , :: diesel :: result :: Error > > ( ) ? ;
190
+ . collect ( ) ;
194
191
195
192
#[ derive( Serialize ) ]
196
193
struct R {
0 commit comments