mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 03:11:32 +00:00
Filters done, working on tests.
This commit is contained in:
parent
4586947910
commit
389083418c
1 changed files with 259 additions and 146 deletions
|
@ -9,11 +9,13 @@ use crate::structs::{
|
||||||
SearchCombinedViewInternal,
|
SearchCombinedViewInternal,
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
|
dsl::not,
|
||||||
result::Error,
|
result::Error,
|
||||||
BoolExpressionMethods,
|
BoolExpressionMethods,
|
||||||
ExpressionMethods,
|
ExpressionMethods,
|
||||||
JoinOnDsl,
|
JoinOnDsl,
|
||||||
NullableExpressionMethods,
|
NullableExpressionMethods,
|
||||||
|
PgTextExpressionMethods,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
SelectableHelper,
|
SelectableHelper,
|
||||||
};
|
};
|
||||||
|
@ -21,7 +23,7 @@ use diesel_async::RunQueryDsl;
|
||||||
use i_love_jesus::PaginatedQueryBuilder;
|
use i_love_jesus::PaginatedQueryBuilder;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
aliases::creator_community_actions,
|
aliases::creator_community_actions,
|
||||||
newtypes::PersonId,
|
newtypes::{CommunityId, PersonId},
|
||||||
schema::{
|
schema::{
|
||||||
comment,
|
comment,
|
||||||
comment_actions,
|
comment_actions,
|
||||||
|
@ -43,8 +45,10 @@ use lemmy_db_schema::{
|
||||||
combined::search::{search_combined_keys as key, SearchCombined},
|
combined::search::{search_combined_keys as key, SearchCombined},
|
||||||
community::CommunityFollower,
|
community::CommunityFollower,
|
||||||
},
|
},
|
||||||
utils::{actions, actions_alias, functions::coalesce, get_conn, DbPool},
|
utils::{actions, actions_alias, functions::coalesce, fuzzy_search, get_conn, DbPool},
|
||||||
InternalToCombinedView,
|
InternalToCombinedView,
|
||||||
|
ListingType,
|
||||||
|
SearchType,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
@ -84,12 +88,20 @@ impl SearchCombinedPaginationCursor {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PaginationCursorData(SearchCombined);
|
pub struct PaginationCursorData(SearchCombined);
|
||||||
|
|
||||||
#[derive(derive_new::new)]
|
#[derive(Default)]
|
||||||
pub struct SearchCombinedQuery {
|
pub struct SearchCombinedQuery {
|
||||||
pub creator_id: PersonId,
|
pub search_term: Option<String>,
|
||||||
#[new(default)]
|
pub community_id: Option<CommunityId>,
|
||||||
|
pub creator_id: Option<PersonId>,
|
||||||
|
pub type_: Option<SearchType>,
|
||||||
|
// TODO sorts need to be added
|
||||||
|
// pub sort: Option<PostSortType>,
|
||||||
|
pub listing_type: Option<ListingType>,
|
||||||
|
pub title_only: Option<bool>,
|
||||||
|
pub post_url_only: Option<bool>,
|
||||||
|
pub liked_only: Option<bool>,
|
||||||
|
pub disliked_only: Option<bool>,
|
||||||
pub page_after: Option<PaginationCursorData>,
|
pub page_after: Option<PaginationCursorData>,
|
||||||
#[new(default)]
|
|
||||||
pub page_back: Option<bool>,
|
pub page_back: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +144,7 @@ impl SearchCombinedQuery {
|
||||||
// For example, the creator must be the person table joined to either:
|
// For example, the creator must be the person table joined to either:
|
||||||
// - post.creator_id
|
// - post.creator_id
|
||||||
// - comment.creator_id
|
// - comment.creator_id
|
||||||
let query = search_combined::table
|
let mut query = search_combined::table
|
||||||
// The comment
|
// The comment
|
||||||
.left_join(comment::table.on(comment_join))
|
.left_join(comment::table.on(comment_join))
|
||||||
// The post
|
// The post
|
||||||
|
@ -217,6 +229,112 @@ impl SearchCombinedQuery {
|
||||||
))
|
))
|
||||||
.into_boxed();
|
.into_boxed();
|
||||||
|
|
||||||
|
// The filters
|
||||||
|
|
||||||
|
// The search term
|
||||||
|
if let Some(search_term) = &self.search_term {
|
||||||
|
if self.post_url_only.unwrap_or_default() {
|
||||||
|
query = query.filter(post::url.eq(search_term));
|
||||||
|
} else {
|
||||||
|
let searcher = fuzzy_search(search_term);
|
||||||
|
|
||||||
|
let name_or_title_filter = post::name
|
||||||
|
.ilike(searcher.clone())
|
||||||
|
.or(comment::content.ilike(searcher.clone()))
|
||||||
|
.or(community::name.ilike(searcher.clone()))
|
||||||
|
.or(community::title.ilike(searcher.clone()))
|
||||||
|
.or(person::name.ilike(searcher.clone()))
|
||||||
|
.or(person::display_name.ilike(searcher.clone()));
|
||||||
|
|
||||||
|
let body_or_description_filter = post::body
|
||||||
|
.ilike(searcher.clone())
|
||||||
|
.or(community::description.ilike(searcher.clone()));
|
||||||
|
|
||||||
|
query = if self.title_only.unwrap_or_default() {
|
||||||
|
query.filter(name_or_title_filter)
|
||||||
|
} else {
|
||||||
|
query.filter(name_or_title_filter.or(body_or_description_filter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Community id
|
||||||
|
if let Some(community_id) = self.community_id {
|
||||||
|
query = query.filter(community::id.eq(community_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creator id
|
||||||
|
if let Some(creator_id) = self.creator_id {
|
||||||
|
query = query.filter(item_creator.eq(creator_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liked / disliked filter
|
||||||
|
if let Some(my_id) = my_person_id {
|
||||||
|
let not_creator_filter = item_creator.ne(my_id);
|
||||||
|
// TODO do I need not null checks for these?
|
||||||
|
let liked_disliked_filter = |score: i16| {
|
||||||
|
search_combined::post_id
|
||||||
|
.is_not_null()
|
||||||
|
.and(post_actions::like_score.eq(score))
|
||||||
|
.or(
|
||||||
|
search_combined::comment_id
|
||||||
|
.is_not_null()
|
||||||
|
.and(comment_actions::like_score.eq(score)),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.liked_only.unwrap_or_default() {
|
||||||
|
query = query
|
||||||
|
.filter(not_creator_filter)
|
||||||
|
.filter(liked_disliked_filter(1));
|
||||||
|
} else if self.disliked_only.unwrap_or_default() {
|
||||||
|
query = query
|
||||||
|
.filter(not_creator_filter)
|
||||||
|
.filter(liked_disliked_filter(-1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Type
|
||||||
|
if let Some(type_) = self.type_ {
|
||||||
|
query = match type_ {
|
||||||
|
SearchType::All => query,
|
||||||
|
SearchType::Posts => query.filter(search_combined::post_id.is_not_null()),
|
||||||
|
SearchType::Comments => query.filter(search_combined::comment_id.is_not_null()),
|
||||||
|
SearchType::Communities => query.filter(search_combined::community_id.is_not_null()),
|
||||||
|
SearchType::Users => query.filter(search_combined::person_id.is_not_null()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listing type
|
||||||
|
// TODO need null checks for this one?
|
||||||
|
let is_subscribed = community_actions::followed.is_not_null();
|
||||||
|
match self.listing_type.unwrap_or_default() {
|
||||||
|
ListingType::Subscribed => query = query.filter(is_subscribed),
|
||||||
|
ListingType::Local => {
|
||||||
|
query = query
|
||||||
|
.filter(community::local.eq(true))
|
||||||
|
.filter(community::hidden.eq(false).or(is_subscribed));
|
||||||
|
}
|
||||||
|
ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)),
|
||||||
|
ListingType::ModeratorView => {
|
||||||
|
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleted / removed filters
|
||||||
|
// TODO need null checks for this?
|
||||||
|
query = query.filter(not(
|
||||||
|
comment::removed
|
||||||
|
.or(comment::deleted)
|
||||||
|
.or(post::removed)
|
||||||
|
.or(post::deleted)
|
||||||
|
.or(community::removed)
|
||||||
|
.or(community::deleted)
|
||||||
|
.or(community::removed)
|
||||||
|
.or(community::deleted)
|
||||||
|
.or(person::deleted),
|
||||||
|
));
|
||||||
|
|
||||||
let mut query = PaginatedQueryBuilder::new(query);
|
let mut query = PaginatedQueryBuilder::new(query);
|
||||||
|
|
||||||
let page_after = self.page_after.map(|c| c.0);
|
let page_after = self.page_after.map(|c| c.0);
|
||||||
|
@ -311,164 +429,159 @@ impl InternalToCombinedView for SearchCombinedViewInternal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(test)]
|
#[cfg(test)]
|
||||||
// #[expect(clippy::indexing_slicing)]
|
#[expect(clippy::indexing_slicing)]
|
||||||
// mod tests {
|
mod tests {
|
||||||
|
|
||||||
// use crate::{
|
use crate::{combined::search_combined_view::SearchCombinedQuery, structs::SearchCombinedView};
|
||||||
// combined::search_combined_view::SearchCombinedQuery,
|
use lemmy_db_schema::{
|
||||||
// structs::SearchCombinedView,
|
assert_length,
|
||||||
// };
|
source::{
|
||||||
// use lemmy_db_schema::{
|
comment::{Comment, CommentInsertForm},
|
||||||
// source::{
|
community::{Community, CommunityInsertForm},
|
||||||
// comment::{Comment, CommentInsertForm},
|
instance::Instance,
|
||||||
// community::{Community, CommunityInsertForm},
|
person::{Person, PersonInsertForm},
|
||||||
// instance::Instance,
|
post::{Post, PostInsertForm},
|
||||||
// person::{Person, PersonInsertForm},
|
},
|
||||||
// post::{Post, PostInsertForm},
|
traits::Crud,
|
||||||
// },
|
utils::{build_db_pool_for_tests, DbPool},
|
||||||
// traits::Crud,
|
};
|
||||||
// utils::{build_db_pool_for_tests, DbPool},
|
use lemmy_utils::error::LemmyResult;
|
||||||
// };
|
use pretty_assertions::assert_eq;
|
||||||
// use lemmy_utils::error::LemmyResult;
|
use serial_test::serial;
|
||||||
// use pretty_assertions::assert_eq;
|
|
||||||
// use serial_test::serial;
|
|
||||||
|
|
||||||
// struct Data {
|
struct Data {
|
||||||
// instance: Instance,
|
instance: Instance,
|
||||||
// timmy: Person,
|
timmy: Person,
|
||||||
// sara: Person,
|
sara: Person,
|
||||||
// timmy_post: Post,
|
community: Community,
|
||||||
// timmy_post_2: Post,
|
community_2: Community,
|
||||||
// sara_post: Post,
|
timmy_post: Post,
|
||||||
// timmy_comment: Comment,
|
timmy_post_2: Post,
|
||||||
// sara_comment: Comment,
|
sara_post: Post,
|
||||||
// sara_comment_2: Comment,
|
timmy_comment: Comment,
|
||||||
// }
|
sara_comment: Comment,
|
||||||
|
sara_comment_2: Comment,
|
||||||
|
}
|
||||||
|
|
||||||
// async fn init_data(pool: &mut DbPool<'_>) -> LemmyResult<Data> {
|
async fn init_data(pool: &mut DbPool<'_>) -> LemmyResult<Data> {
|
||||||
// let instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
let instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||||
|
|
||||||
// let timmy_form = PersonInsertForm::test_form(instance.id, "timmy_pcv");
|
let timmy_form = PersonInsertForm::test_form(instance.id, "timmy_pcv");
|
||||||
// let timmy = Person::create(pool, &timmy_form).await?;
|
let timmy = Person::create(pool, &timmy_form).await?;
|
||||||
|
|
||||||
// let sara_form = PersonInsertForm::test_form(instance.id, "sara_pcv");
|
let sara_form = PersonInsertForm::test_form(instance.id, "sara_pcv");
|
||||||
// let sara = Person::create(pool, &sara_form).await?;
|
let sara = Person::create(pool, &sara_form).await?;
|
||||||
|
|
||||||
// let community_form = CommunityInsertForm::new(
|
let community_form = CommunityInsertForm::new(
|
||||||
// instance.id,
|
instance.id,
|
||||||
// "test community pcv".to_string(),
|
"asklemmy".to_string(),
|
||||||
// "nada".to_owned(),
|
"Ask Lemmy".to_owned(),
|
||||||
// "pubkey".to_string(),
|
"pubkey".to_string(),
|
||||||
// );
|
);
|
||||||
// let community = Community::create(pool, &community_form).await?;
|
let community = Community::create(pool, &community_form).await?;
|
||||||
|
|
||||||
// let timmy_post_form = PostInsertForm::new("timmy post prv".into(), timmy.id, community.id);
|
let community_form_2 = CommunityInsertForm::new(
|
||||||
// let timmy_post = Post::create(pool, &timmy_post_form).await?;
|
instance.id,
|
||||||
|
"startrek_ds9".to_string(),
|
||||||
|
"Star Trek - Deep Space Nine".to_owned(),
|
||||||
|
"pubkey".to_string(),
|
||||||
|
);
|
||||||
|
let community_2 = Community::create(pool, &community_form_2).await?;
|
||||||
|
|
||||||
// let timmy_post_form_2 = PostInsertForm::new("timmy post prv 2".into(), timmy.id,
|
let timmy_post_form = PostInsertForm::new("timmy post prv".into(), timmy.id, community.id);
|
||||||
// community.id); let timmy_post_2 = Post::create(pool, &timmy_post_form_2).await?;
|
let timmy_post = Post::create(pool, &timmy_post_form).await?;
|
||||||
|
|
||||||
// let sara_post_form = PostInsertForm::new("sara post prv".into(), sara.id, community.id);
|
let timmy_post_form_2 = PostInsertForm::new("timmy post prv 2".into(), timmy.id, community.id);
|
||||||
// let sara_post = Post::create(pool, &sara_post_form).await?;
|
let timmy_post_2 = Post::create(pool, &timmy_post_form_2).await?;
|
||||||
|
|
||||||
// let timmy_comment_form =
|
let sara_post_form = PostInsertForm::new("sara post prv".into(), sara.id, community.id);
|
||||||
// CommentInsertForm::new(timmy.id, timmy_post.id, "timmy comment prv".into());
|
let sara_post = Post::create(pool, &sara_post_form).await?;
|
||||||
// let timmy_comment = Comment::create(pool, &timmy_comment_form, None).await?;
|
|
||||||
|
|
||||||
// let sara_comment_form =
|
let timmy_comment_form =
|
||||||
// CommentInsertForm::new(sara.id, timmy_post.id, "sara comment prv".into());
|
CommentInsertForm::new(timmy.id, timmy_post.id, "timmy comment prv".into());
|
||||||
// let sara_comment = Comment::create(pool, &sara_comment_form, None).await?;
|
let timmy_comment = Comment::create(pool, &timmy_comment_form, None).await?;
|
||||||
|
|
||||||
// let sara_comment_form_2 =
|
let sara_comment_form =
|
||||||
// CommentInsertForm::new(sara.id, timmy_post_2.id, "sara comment prv 2".into());
|
CommentInsertForm::new(sara.id, timmy_post.id, "sara comment prv".into());
|
||||||
// let sara_comment_2 = Comment::create(pool, &sara_comment_form_2, None).await?;
|
let sara_comment = Comment::create(pool, &sara_comment_form, None).await?;
|
||||||
|
|
||||||
// Ok(Data {
|
let sara_comment_form_2 =
|
||||||
// instance,
|
CommentInsertForm::new(sara.id, timmy_post_2.id, "sara comment prv 2".into());
|
||||||
// timmy,
|
let sara_comment_2 = Comment::create(pool, &sara_comment_form_2, None).await?;
|
||||||
// sara,
|
|
||||||
// timmy_post,
|
|
||||||
// timmy_post_2,
|
|
||||||
// sara_post,
|
|
||||||
// timmy_comment,
|
|
||||||
// sara_comment,
|
|
||||||
// sara_comment_2,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
Ok(Data {
|
||||||
// Instance::delete(pool, data.instance.id).await?;
|
instance,
|
||||||
|
timmy,
|
||||||
|
sara,
|
||||||
|
community,
|
||||||
|
community_2,
|
||||||
|
timmy_post,
|
||||||
|
timmy_post_2,
|
||||||
|
sara_post,
|
||||||
|
timmy_comment,
|
||||||
|
sara_comment,
|
||||||
|
sara_comment_2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Ok(())
|
async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
||||||
// }
|
Instance::delete(pool, data.instance.id).await?;
|
||||||
|
|
||||||
// #[tokio::test]
|
Ok(())
|
||||||
// #[serial]
|
}
|
||||||
// async fn test_combined() -> LemmyResult<()> {
|
|
||||||
// let pool = &build_db_pool_for_tests();
|
|
||||||
// let pool = &mut pool.into();
|
|
||||||
// let data = init_data(pool).await?;
|
|
||||||
|
|
||||||
// // Do a batch read of timmy
|
#[tokio::test]
|
||||||
// let timmy_content = SearchCombinedQuery::new(data.timmy.id)
|
#[serial]
|
||||||
// .list(pool, &None)
|
async fn community_search() -> LemmyResult<()> {
|
||||||
// .await?;
|
let pool = &build_db_pool_for_tests();
|
||||||
// assert_eq!(3, timmy_content.len());
|
let pool = &mut pool.into();
|
||||||
|
let data = init_data(pool).await?;
|
||||||
|
|
||||||
// // Make sure the types are correct
|
// Community search
|
||||||
// if let SearchCombinedView::Comment(v) = &timmy_content[0] {
|
let community_search = SearchCombinedQuery::default().list(pool, &None).await?;
|
||||||
// assert_eq!(data.timmy_comment.id, v.comment.id);
|
assert_length!(2, community_search);
|
||||||
// assert_eq!(data.timmy.id, v.creator.id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
// if let SearchCombinedView::Post(v) = &timmy_content[1] {
|
|
||||||
// assert_eq!(data.timmy_post_2.id, v.post.id);
|
|
||||||
// assert_eq!(data.timmy.id, v.post.creator_id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
// if let SearchCombinedView::Post(v) = &timmy_content[2] {
|
|
||||||
// assert_eq!(data.timmy_post.id, v.post.id);
|
|
||||||
// assert_eq!(data.timmy.id, v.post.creator_id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Do a batch read of sara
|
// Make sure the types are correct
|
||||||
// let sara_content = SearchCombinedQuery::new(data.sara.id)
|
if let SearchCombinedView::Community(v) = &community_search[0] {
|
||||||
// .list(pool, &None)
|
assert_eq!(data.community_2.id, v.community.id);
|
||||||
// .await?;
|
} else {
|
||||||
// assert_eq!(3, sara_content.len());
|
panic!("wrong type");
|
||||||
|
}
|
||||||
|
|
||||||
// // Make sure the report types are correct
|
if let SearchCombinedView::Community(v) = &community_search[1] {
|
||||||
// if let SearchCombinedView::Comment(v) = &sara_content[0] {
|
assert_eq!(data.community.id, v.community.id);
|
||||||
// assert_eq!(data.sara_comment_2.id, v.comment.id);
|
} else {
|
||||||
// assert_eq!(data.sara.id, v.creator.id);
|
panic!("wrong type");
|
||||||
// // This one was to timmy_post_2
|
}
|
||||||
// assert_eq!(data.timmy_post_2.id, v.post.id);
|
|
||||||
// assert_eq!(data.timmy.id, v.post.creator_id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
// if let SearchCombinedView::Comment(v) = &sara_content[1] {
|
|
||||||
// assert_eq!(data.sara_comment.id, v.comment.id);
|
|
||||||
// assert_eq!(data.sara.id, v.creator.id);
|
|
||||||
// assert_eq!(data.timmy_post.id, v.post.id);
|
|
||||||
// assert_eq!(data.timmy.id, v.post.creator_id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
// if let SearchCombinedView::Post(v) = &sara_content[2] {
|
|
||||||
// assert_eq!(data.sara_post.id, v.post.id);
|
|
||||||
// assert_eq!(data.sara.id, v.post.creator_id);
|
|
||||||
// } else {
|
|
||||||
// panic!("wrong type");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// cleanup(data, pool).await?;
|
// Filtered by id
|
||||||
|
let community_search_by_id = SearchCombinedQuery {
|
||||||
|
community_id: Some(data.community.id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(pool, &None)
|
||||||
|
.await?;
|
||||||
|
assert_length!(1, community_search_by_id);
|
||||||
|
|
||||||
// Ok(())
|
// Using a term
|
||||||
// }
|
let community_search_by_name = SearchCombinedQuery {
|
||||||
// }
|
search_term: Some("Ask".into()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(pool, &None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_length!(1, community_search_by_name);
|
||||||
|
if let SearchCombinedView::Community(v) = &community_search_by_name[0] {
|
||||||
|
// The asklemmy community
|
||||||
|
assert_eq!(data.community.id, v.community.id);
|
||||||
|
} else {
|
||||||
|
panic!("wrong type");
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup(data, pool).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue