Use TagDao for improved filtering

This commit is contained in:
Cameron
2024-11-24 09:49:03 -05:00
parent 9a32a1cfe7
commit 860e7a97fb
3 changed files with 50 additions and 55 deletions

View File

@@ -24,7 +24,7 @@ use crate::tags::TagDao;
use crate::video::StreamActor; use crate::video::StreamActor;
use path_absolutize::*; use path_absolutize::*;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use rand::{thread_rng}; use rand::thread_rng;
use serde::Deserialize; use serde::Deserialize;
pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>( pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
@@ -51,43 +51,27 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
.filter_map(|t| t.parse().ok()) .filter_map(|t| t.parse().ok())
.collect::<Vec<i32>>(); .collect::<Vec<i32>>();
let exclude_tag_ids = req.exclude_tag_ids.clone() let exclude_tag_ids = req
.exclude_tag_ids
.clone()
.unwrap_or(String::new()) .unwrap_or(String::new())
.split(',') .split(',')
.filter_map(|t| t.parse().ok()) .filter_map(|t| t.parse().ok())
.collect::<Vec<i32>>(); .collect::<Vec<i32>>();
return dao match filter_mode {
.get_files_with_any_tag_ids(tag_ids.clone(), exclude_tag_ids.clone()) FilterMode::Any => dao.get_files_with_any_tag_ids(tag_ids.clone(), exclude_tag_ids),
.context(format!("Failed to get files with tag_ids: {:?}", tag_ids)) FilterMode::All => dao.get_files_with_all_tag_ids(tag_ids.clone(), exclude_tag_ids),
.map(|tagged_files| {
return if let Some(sort_type) = req.sort {
debug!("Sorting files: {:?}", sort_type);
sort(tagged_files, sort_type)
} else {
tagged_files
};
})
.map(|tagged_files| match filter_mode {
FilterMode::Any => tagged_files
.iter()
.filter(|file| file.starts_with(search_path))
.cloned()
.collect(),
FilterMode::All => tagged_files
.iter()
.filter(|&file_path| {
if !file_path.starts_with(search_path) {
return false;
} }
.context(format!(
let file_tags = dao.get_tags_for_path(file_path).unwrap_or_default(); "Failed to get files with tag_ids: {:?} with filter_mode: {:?}",
tag_ids tag_ids, filter_mode
.iter() ))
.all(|id| file_tags.iter().any(|tag| &tag.id == id)) .map(|files| {
}) files
.cloned() .into_iter()
.collect::<Vec<String>>(), .filter(|file_path| file_path.starts_with(search_path))
.collect()
}) })
.map(|tagged_files| { .map(|tagged_files| {
trace!("Found tagged files: {:?}", tagged_files); trace!("Found tagged files: {:?}", tagged_files);

View File

@@ -548,7 +548,8 @@ fn watch_files() {
let base_str = dotenv::var("BASE_PATH").unwrap(); let base_str = dotenv::var("BASE_PATH").unwrap();
let base_path = Path::new(&base_str); let base_path = Path::new(&base_str);
watcher.watch(base_path, RecursiveMode::Recursive) watcher
.watch(base_path, RecursiveMode::Recursive)
.context(format!("Unable to watch BASE_PATH: '{}'", base_str)) .context(format!("Unable to watch BASE_PATH: '{}'", base_str))
.unwrap(); .unwrap();

View File

@@ -198,7 +198,11 @@ pub trait TagDao {
fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>; fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>;
fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>; fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>;
fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>; fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>;
fn get_files_with_all_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>>; fn get_files_with_all_tag_ids(
&mut self,
tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>>;
fn get_files_with_any_tag_ids( fn get_files_with_any_tag_ids(
&mut self, &mut self,
tag_ids: Vec<i32>, tag_ids: Vec<i32>,
@@ -345,11 +349,16 @@ impl TagDao for SqliteTagDao {
}) })
} }
fn get_files_with_all_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>> { fn get_files_with_all_tag_ids(
&mut self,
tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>> {
use diesel::dsl::*; use diesel::dsl::*;
tagged_photo::table tagged_photo::table
.filter(tagged_photo::tag_id.eq_any(tag_ids.clone())) .filter(tagged_photo::tag_id.eq_any(tag_ids.clone()))
.filter(tagged_photo::tag_id.ne_all(exclude_tag_ids))
.group_by(tagged_photo::photo_name) .group_by(tagged_photo::photo_name)
.select((tagged_photo::photo_name, count(tagged_photo::tag_id))) .select((tagged_photo::photo_name, count(tagged_photo::tag_id)))
.having(count_distinct(tagged_photo::tag_id).eq(tag_ids.len() as i64)) .having(count_distinct(tagged_photo::tag_id).eq(tag_ids.len() as i64))
@@ -496,7 +505,8 @@ mod tests {
fn get_files_with_all_tag_ids( fn get_files_with_all_tag_ids(
&mut self, &mut self,
_tag_ids: Vec<i32>, tag_ids: Vec<i32>,
exclude_tag_ids: Vec<i32>,
) -> anyhow::Result<Vec<String>> { ) -> anyhow::Result<Vec<String>> {
todo!() todo!()
} }