Skip to content

Commit

Permalink
search impl (#4)
Browse files Browse the repository at this point in the history
* search impl

* typo

* fixed sqls
  • Loading branch information
tikitko authored Jul 10, 2023
1 parent 3224b2e commit efdf125
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 15 deletions.
17 changes: 13 additions & 4 deletions blog-server-api/src/endpoints/authors/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,25 @@ use screw_api::response::ApiResponse;
use std::sync::Arc;

async fn handler(
query: Option<String>,
offset: Option<i64>,
limit: Option<i64>,
author_service: Arc<Box<dyn AuthorService>>,
) -> Result<AuthorsResponseContentSuccess, AuthorsResponseContentFailure> {
let offset = offset.unwrap_or(0).max(0);
let limit = limit.unwrap_or(50).max(0).min(50);

let (authors_result, total_result) = tokio::join!(
author_service.authors(&offset, &limit),
author_service.authors_count(),
);
let (authors_result, total_result) = if let Some(query) = query {
tokio::join!(
author_service.authors_by_query(&query, &offset, &limit),
author_service.authors_count_by_query(&query),
)
} else {
tokio::join!(
author_service.authors(&offset, &limit),
author_service.authors_count(),
)
};

let authors = authors_result
.map_err(|e| DatabaseError {
Expand Down Expand Up @@ -49,6 +57,7 @@ where
{
ApiResponse::from(
handler(
request.content.query,
request.content.offset,
request.content.limit,
request.content.author_service,
Expand Down
2 changes: 2 additions & 0 deletions blog-server-api/src/endpoints/authors/request_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use screw_api::request::{ApiRequestContent, ApiRequestOriginContent};
use std::sync::Arc;

pub struct AuthorsRequestContent {
pub(super) query: Option<String>,
pub(super) offset: Option<i64>,
pub(super) limit: Option<i64>,
pub(super) author_service: Arc<Box<dyn AuthorService>>,
Expand All @@ -17,6 +18,7 @@ where

fn create(origin_content: ApiRequestOriginContent<Self::Data, Extensions>) -> Self {
Self {
query: origin_content.path.get("query").map(|n| n.to_owned()),
offset: origin_content
.query
.get("offset")
Expand Down
18 changes: 13 additions & 5 deletions blog-server-api/src/endpoints/posts/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,27 @@ use blog_server_services::traits::post_service::PostService;
use screw_api::request::ApiRequest;
use screw_api::response::ApiResponse;
use std::sync::Arc;
use tokio::join;

async fn handler(
query: Option<String>,
offset: Option<i64>,
limit: Option<i64>,
post_service: Arc<Box<dyn PostService>>,
) -> Result<PostsResponseContentSuccess, PostsResponseContentFailure> {
let offset = offset.unwrap_or(0).max(0);
let limit = limit.unwrap_or(50).max(0).min(50);

let (posts_result, total_result) = join!(
post_service.posts(&offset, &limit),
post_service.posts_count(),
);
let (posts_result, total_result) = if let Some(query) = query {
tokio::join!(
post_service.posts_by_query(&query, &offset, &limit),
post_service.posts_count_by_query(&query),
)
} else {
tokio::join!(
post_service.posts(&offset, &limit),
post_service.posts_count(),
)
};

let posts = posts_result
.map_err(|e| DatabaseError {
Expand Down Expand Up @@ -50,6 +57,7 @@ where
{
ApiResponse::from(
handler(
request.content.query,
request.content.offset,
request.content.limit,
request.content.post_service,
Expand Down
2 changes: 2 additions & 0 deletions blog-server-api/src/endpoints/posts/request_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use screw_api::request::{ApiRequestContent, ApiRequestOriginContent};
use std::sync::Arc;

pub struct PostsRequestContent {
pub(super) query: Option<String>,
pub(super) offset: Option<i64>,
pub(super) limit: Option<i64>,
pub(super) post_service: Arc<Box<dyn PostService>>,
Expand All @@ -17,6 +18,7 @@ where

fn create(origin_content: ApiRequestOriginContent<Self::Data, Extensions>) -> Self {
Self {
query: origin_content.path.get("query").map(|n| n.to_owned()),
offset: origin_content
.query
.get("offset")
Expand Down
30 changes: 29 additions & 1 deletion blog-server-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,36 @@ async fn main() -> screw_components::dyn_result::DResult<()> {
Ok(())
}

#[derive(Debug)]
struct DbgRbatisIntercept;

impl rbatis::intercept::Intercept for DbgRbatisIntercept {
fn before(
&self,
_task_id: i64,
_rb: &dyn rbatis::executor::Executor,
sql: &mut String,
args: &mut Vec<rbs::Value>,
) -> Result<(), rbatis::Error> {
dbg!(sql);
dbg!(args);
Ok(())
}
}

pub async fn init_db() -> rbatis::RBatis {
let rb = rbatis::RBatis::new();
let opt = rbatis::RBatisOption {
intercepts: {
let intercepts: rbatis::dark_std::sync::SyncVec<
std::sync::Arc<dyn rbatis::intercept::Intercept>,
> = rbatis::dark_std::sync::SyncVec::new();
if cfg!(debug_assertions) {
intercepts.push(std::sync::Arc::new(DbgRbatisIntercept));
}
intercepts
},
};
let rb = rbatis::RBatis::new_with_opt(opt);
rb.init(
rbdc_pg::driver::PgDriver {},
std::env::var("PG_URL")
Expand Down
12 changes: 12 additions & 0 deletions blog-server-api/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ pub fn make_router<Extensions: ExtensionsProviderType>(
.and_path("/posts")
.and_handler(posts::http_handler),
)
.scoped("/search", |r| {
r.route(
route::first::Route::with_method(&hyper::Method::GET)
.and_path("/posts/{query:[^/]*}")
.and_handler(posts::http_handler),
)
.route(
route::first::Route::with_method(&hyper::Method::GET)
.and_path("/authors/{query:[^/]*}")
.and_handler(authors::http_handler),
)
})
.route(
route::first::Route::with_method(&hyper::Method::GET)
.and_path("/comments/{post_slug:[^/]*}")
Expand Down
38 changes: 35 additions & 3 deletions blog-server-services/src/impls/rbatis_author_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ pub fn create_rbatis_author_service(rb: RBatis) -> Box<dyn AuthorService> {
}

impl_insert!(BaseAuthor {}, "author");
impl_select!(Author {select_by_id(id: &i64) -> Option => "`WHERE id = #{id} LIMIT 1`"});
impl_select!(Author {select_by_slug(slug: &String) -> Option => "`WHERE slug = #{slug} LIMIT 1`"});
impl_select!(Author {select_all_with_offset_and_limit(offset: &i64, limit: &i64) => "`LIMIT #{limit} OFFSET #{offset}`"});
impl_select!(Author {select_by_id(id: &i64) -> Option =>
"`WHERE id = #{id} LIMIT 1`"});
impl_select!(Author {select_by_slug(slug: &String) -> Option =>
"`WHERE slug = #{slug} LIMIT 1`"});
impl_select!(Author {select_all_with_offset_and_limit(offset: &i64, limit: &i64) =>
"`LIMIT #{limit} OFFSET #{offset}`"});
impl_select!(Author {select_all_by_query_with_offset_and_limit(query: &String, offset: &i64, limit: &i64) =>
"`WHERE author.slug ILIKE '%' || #{query} || '%' OR author.first_name ILIKE '%' || #{query} || '%' OR author.middle_name ILIKE '%' || #{query} || '%' OR author.last_name ILIKE '%' || #{query} || '%' LIMIT #{limit} OFFSET #{offset}`"});

impl Author {
#[py_sql(
Expand All @@ -21,6 +26,16 @@ impl Author {
async fn count(rb: &RBatis) -> rbatis::Result<i64> {
impled!()
}
#[py_sql(
"
SELECT COUNT(1) \
FROM author \
WHERE author.slug ILIKE '%' || #{query} || '%' OR author.first_name ILIKE '%' || #{query} || '%' OR author.middle_name ILIKE '%' || #{query} || '%' OR author.last_name ILIKE '%' || #{query} || '%' \
"
)]
async fn count_by_query(rb: &RBatis, query: &String) -> rbatis::Result<i64> {
impled!()
}
}

struct RbatisAuthorService {
Expand All @@ -29,6 +44,23 @@ struct RbatisAuthorService {

#[async_trait]
impl AuthorService for RbatisAuthorService {
async fn authors_count_by_query(&self, query: &String) -> DResult<i64> {
Ok(Author::count_by_query(&self.rb, query).await?)
}
async fn authors_by_query(
&self,
query: &String,
offset: &i64,
limit: &i64,
) -> DResult<Vec<Author>> {
Ok(Author::select_all_by_query_with_offset_and_limit(
&mut self.rb.clone(),
query,
offset,
limit,
)
.await?)
}
async fn authors_count(&self) -> DResult<i64> {
Ok(Author::count(&self.rb).await?)
}
Expand Down
4 changes: 2 additions & 2 deletions blog-server-services/src/impls/rbatis_comment_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Comment {
OFFSET #{offset} \
"
)]
async fn select_all_with_post_id_and_limit_and_offset(
async fn select_all_by_post_id_with_limit_and_offset(
rb: &RBatis,
post_id: &i64,
limit: &i64,
Expand All @@ -59,7 +59,7 @@ impl CommentService for RbatisCommentService {
limit: &i64,
) -> DResult<Vec<Comment>> {
Ok(
Comment::select_all_with_post_id_and_limit_and_offset(&self.rb, post_id, limit, offset)
Comment::select_all_by_post_id_with_limit_and_offset(&self.rb, post_id, limit, offset)
.await?,
)
}
Expand Down
47 changes: 47 additions & 0 deletions blog-server-services/src/impls/rbatis_post_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ impl Post {
async fn count(rb: &RBatis) -> rbatis::Result<i64> {
impled!()
}
#[py_sql(
"
SELECT COUNT(1) \
FROM post \
WHERE post.title ILIKE '%' || #{query} || '%' OR post.summary ILIKE '%' || #{query} || '%' OR post.content ILIKE '%' || #{query} || '%' \
"
)]
async fn count_by_query(rb: &RBatis, query: &String) -> rbatis::Result<i64> {
impled!()
}
#[py_sql(
"
SELECT \
Expand Down Expand Up @@ -82,6 +92,32 @@ impl Post {
) -> rbatis::Result<Vec<Post>> {
impled!()
}
#[py_sql(
"
SELECT \
post.*, \
author.slug AS author_slug, \
author.first_name AS author_first_name, \
author.last_name AS author_last_name, \
string_agg(concat_ws(',', tag.slug, tag.title), ';') as tags \
FROM post \
JOIN author ON post.author_id = author.id \
LEFT JOIN post_tag ON post_tag.post_id = post.id \
LEFT JOIN tag ON tag.id = post_tag.tag_id \
WHERE post.title ILIKE '%' || #{query} || '%' OR post.summary ILIKE '%' || #{query} || '%' OR post.content ILIKE '%' || #{query} || '%' \
GROUP BY post.id, author.slug, author.first_name, author.last_name \
LIMIT #{limit} \
OFFSET #{offset} \
"
)]
async fn select_all_by_query_with_limit_and_offset(
rb: &RBatis,
query: &String,
limit: &i64,
offset: &i64,
) -> rbatis::Result<Vec<Post>> {
impled!()
}
}

struct RbatisPostService {
Expand All @@ -90,6 +126,17 @@ struct RbatisPostService {

#[async_trait]
impl PostService for RbatisPostService {
async fn posts_count_by_query(&self, query: &String) -> DResult<i64> {
Ok(Post::count_by_query(&self.rb, query).await?)
}
async fn posts_by_query(
&self,
query: &String,
offset: &i64,
limit: &i64,
) -> DResult<Vec<Post>> {
Ok(Post::select_all_by_query_with_limit_and_offset(&self.rb, query, limit, offset).await?)
}
async fn posts_count(&self) -> DResult<i64> {
Ok(Post::count(&self.rb).await?)
}
Expand Down
7 changes: 7 additions & 0 deletions blog-server-services/src/traits/author_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ pub struct Author {

#[async_trait]
pub trait AuthorService: Send + Sync {
async fn authors_count_by_query(&self, query: &String) -> DResult<i64>;
async fn authors_by_query(
&self,
query: &String,
offset: &i64,
limit: &i64,
) -> DResult<Vec<Author>>;
async fn authors_count(&self) -> DResult<i64>;
async fn authors(&self, offset: &i64, limit: &i64) -> DResult<Vec<Author>>;
async fn author_by_id(&self, id: &i64) -> DResult<Option<Author>>;
Expand Down
3 changes: 3 additions & 0 deletions blog-server-services/src/traits/post_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub struct Post {

#[async_trait]
pub trait PostService: Send + Sync {
async fn posts_count_by_query(&self, query: &String) -> DResult<i64>;
async fn posts_by_query(&self, query: &String, offset: &i64, limit: &i64)
-> DResult<Vec<Post>>;
async fn posts_count(&self) -> DResult<i64>;
async fn posts(&self, offset: &i64, limit: &i64) -> DResult<Vec<Post>>;
async fn post_by_id(&self, id: &i64) -> DResult<Option<Post>>;
Expand Down

0 comments on commit efdf125

Please sign in to comment.