feat(db): Add view for ordering thread index by most recent post
This implements the classic thread ordering expected by most forum users (i.e. the thread with the most recent post is at the top).
This commit is contained in:
		
							parent
							
								
									cf64826e4e
								
							
						
					
					
						commit
						f10bd20276
					
				
					 6 changed files with 45 additions and 7 deletions
				
			
		
							
								
								
									
										1
									
								
								migrations/2018-04-14-145711_create_index_view/down.sql
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								migrations/2018-04-14-145711_create_index_view/down.sql
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | DROP VIEW thread_index; | ||||||
							
								
								
									
										15
									
								
								migrations/2018-04-14-145711_create_index_view/up.sql
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								migrations/2018-04-14-145711_create_index_view/up.sql
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | -- Create a simple view that returns the list of threads ordered by | ||||||
|  | -- the last post that occured in the thread. | ||||||
|  | 
 | ||||||
|  | CREATE VIEW thread_index AS | ||||||
|  |   SELECT t.id AS thread_id, | ||||||
|  |          t.title AS title, | ||||||
|  |          t.author_name AS author_name, | ||||||
|  |          t.posted AS posted, | ||||||
|  |          p.id AS post_id | ||||||
|  |     FROM threads t | ||||||
|  |     JOIN (SELECT DISTINCT ON (thread_id) id, thread_id | ||||||
|  |           FROM posts | ||||||
|  |           ORDER BY thread_id, id DESC) AS p | ||||||
|  |     ON t.id = p.thread_id | ||||||
|  |     ORDER BY p.id DESC; | ||||||
|  | @ -36,19 +36,18 @@ impl Actor for DbExecutor { | ||||||
| pub struct ListThreads; | pub struct ListThreads; | ||||||
| 
 | 
 | ||||||
| impl Message for ListThreads { | impl Message for ListThreads { | ||||||
|     type Result = Result<Vec<Thread>>; |     type Result = Result<Vec<ThreadIndex>>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Handler<ListThreads> for DbExecutor { | impl Handler<ListThreads> for DbExecutor { | ||||||
|     type Result = <ListThreads as Message>::Result; |     type Result = <ListThreads as Message>::Result; | ||||||
| 
 | 
 | ||||||
|     fn handle(&mut self, _: ListThreads, _: &mut Self::Context) -> Self::Result { |     fn handle(&mut self, _: ListThreads, _: &mut Self::Context) -> Self::Result { | ||||||
|         use schema::threads::dsl::*; |         use schema::thread_index::dsl::*; | ||||||
| 
 | 
 | ||||||
|         let conn = self.0.get()?; |         let conn = self.0.get()?; | ||||||
|         let results = threads |         let results = thread_index | ||||||
|             .order(posted.desc()) |             .load::<ThreadIndex>(&conn)?; | ||||||
|             .load::<Thread>(&conn)?; |  | ||||||
|         Ok(results) |         Ok(results) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -26,6 +26,18 @@ pub struct Thread { | ||||||
|     pub author_email: String, |     pub author_email: String, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// This struct is used as the query type for the thread index view,
 | ||||||
|  | /// which lists the index of threads ordered by the last post in each
 | ||||||
|  | /// thread.
 | ||||||
|  | #[derive(Queryable, Serialize)] | ||||||
|  | pub struct ThreadIndex { | ||||||
|  |     pub thread_id: i32, | ||||||
|  |     pub title: String, | ||||||
|  |     pub author_name: String, | ||||||
|  |     pub posted: DateTime<Utc>, | ||||||
|  |     pub post_id: i32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Identifiable, Queryable, Serialize, Associations)] | #[derive(Identifiable, Queryable, Serialize, Associations)] | ||||||
| #[belongs_to(Thread)] | #[belongs_to(Thread)] | ||||||
| pub struct Post { | pub struct Post { | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ impl From<DateTime<Utc>> for FormattedDate { | ||||||
| 
 | 
 | ||||||
| /// Message used to render the index page.
 | /// Message used to render the index page.
 | ||||||
| pub struct IndexPage { | pub struct IndexPage { | ||||||
|     pub threads: Vec<Thread>, |     pub threads: Vec<ThreadIndex>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Message for IndexPage { | impl Message for IndexPage { | ||||||
|  | @ -69,7 +69,7 @@ impl Handler<IndexPage> for Renderer { | ||||||
|         let threads: Vec<IndexThread> = msg.threads |         let threads: Vec<IndexThread> = msg.threads | ||||||
|             .into_iter() |             .into_iter() | ||||||
|             .map(|thread| IndexThread { |             .map(|thread| IndexThread { | ||||||
|                 id: thread.id, |                 id: thread.thread_id, | ||||||
|                 title: escape_html(&thread.title), |                 title: escape_html(&thread.title), | ||||||
|                 posted: thread.posted.into(), |                 posted: thread.posted.into(), | ||||||
|                 author_name: thread.author_name, |                 author_name: thread.author_name, | ||||||
|  |  | ||||||
|  | @ -19,6 +19,17 @@ table! { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Note: Manually inserted as print-schema does not add views.
 | ||||||
|  | table! { | ||||||
|  |     thread_index (thread_id){ | ||||||
|  |         thread_id -> Integer, | ||||||
|  |         title -> Text, | ||||||
|  |         author_name -> Text, | ||||||
|  |         posted -> Timestamptz, | ||||||
|  |         post_id -> Integer, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| joinable!(posts -> threads (thread_id)); | joinable!(posts -> threads (thread_id)); | ||||||
| 
 | 
 | ||||||
| allow_tables_to_appear_in_same_query!( | allow_tables_to_appear_in_same_query!( | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue