diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs index 602a7ea..e910fe5 100644 --- a/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs @@ -132,6 +132,8 @@ fn build_tag_condition(tag: AddTagDto) -> Condition { .add(tag::Column::Name.eq(tag.name)) .add(namespace::Column::Name.eq(namespace)) } else { - Condition::all().add(tag::Column::Name.eq(tag.name)) + Condition::all() + .add(tag::Column::Name.eq(tag.name)) + .add(tag::Column::NamespaceId.is_null()) } } diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs new file mode 100644 index 0000000..1c00084 --- /dev/null +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs @@ -0,0 +1,90 @@ +use crate::dao::tag::{map_tag_dto, TagDao}; +use crate::dto::TagDto; +use mediarepo_core::error::RepoResult; +use mediarepo_core::itertools::Itertools; +use mediarepo_database::entities::{content_descriptor, content_descriptor_tag, namespace, tag}; +use sea_orm::prelude::*; +use std::collections::HashMap; + +impl TagDao { + #[tracing::instrument(level = "debug", skip(self, cds))] + pub async fn all_for_cds_map( + &self, + cds: Vec>, + ) -> RepoResult, Vec>> { + let mut cd_tag_map = cds + .iter() + .cloned() + .map(|cd| (cd, Vec::new())) + .collect::, Vec>>(); + + let tag_cd_entries = tags_for_cds(&self.ctx.db, cds).await?; + + let tag_ids: Vec = tag_cd_entries + .iter() + .map(|(t, _)| t.tag_id) + .unique() + .collect(); + + let tags = tags_for_tag_ids(&self.ctx.db, tag_ids).await?; + + let tag_id_map = tags + .into_iter() + .map(|t| (t.id(), t)) + .collect::>(); + let existing_cds_with_tags = create_cd_tag_map(tag_cd_entries, tag_id_map); + cd_tag_map.extend(existing_cds_with_tags.into_iter()); + + Ok(cd_tag_map) + } +} + +async fn tags_for_cds( + db: &DatabaseConnection, + cds: Vec>, +) -> RepoResult< + Vec<( + content_descriptor_tag::Model, + Option, + )>, +> { + let tag_cd_entries = content_descriptor_tag::Entity::find() + .find_also_related(content_descriptor::Entity) + .filter(content_descriptor::Column::Descriptor.is_in(cds)) + .all(db) + .await?; + + Ok(tag_cd_entries) +} + +async fn tags_for_tag_ids(db: &DatabaseConnection, ids: Vec) -> RepoResult> { + let tags = tag::Entity::find() + .find_also_related(namespace::Entity) + .filter(tag::Column::Id.is_in(ids)) + .all(db) + .await? + .into_iter() + .map(map_tag_dto) + .collect(); + + Ok(tags) +} + +fn create_cd_tag_map( + tag_cd_entries: Vec<( + content_descriptor_tag::Model, + Option, + )>, + tag_id_map: HashMap, +) -> HashMap, Vec> { + let cd_tag_map = tag_cd_entries + .into_iter() + .filter_map(|(t, cd)| Some((cd?, tag_id_map.get(&t.tag_id)?.clone()))) + .sorted_by_key(|(cd, _)| cd.id) + .group_by(|(cd, _)| cd.descriptor.to_owned()) + .into_iter() + .map(|(key, group)| (key, group.map(|(_, t)| t).collect::>())) + .collect(); + + cd_tag_map +} diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs index 0f44309..80fb2a2 100644 --- a/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs @@ -5,7 +5,6 @@ use std::collections::HashMap; use std::iter::FromIterator; use mediarepo_core::error::RepoResult; -use mediarepo_core::itertools::Itertools; use mediarepo_core::utils::parse_namespace_and_tag; use mediarepo_database::entities::{content_descriptor, content_descriptor_tag, namespace, tag}; @@ -15,6 +14,7 @@ use crate::dao::{DaoContext, DaoProvider}; use crate::dto::{NamespaceDto, TagDto}; pub mod add; +pub mod all_for_cds_map; pub mod by_name; pub mod mappings; @@ -81,51 +81,6 @@ impl TagDao { Ok(tags) } - #[tracing::instrument(level = "debug", skip(self, cds))] - pub async fn all_for_cds_map( - &self, - cds: Vec>, - ) -> RepoResult, Vec>> { - let tag_cd_entries: Vec<( - content_descriptor_tag::Model, - Option, - )> = content_descriptor_tag::Entity::find() - .find_also_related(content_descriptor::Entity) - .filter(content_descriptor::Column::Descriptor.is_in(cds)) - .all(&self.ctx.db) - .await?; - - let tag_ids: Vec = tag_cd_entries - .iter() - .map(|(t, _)| t.tag_id) - .unique() - .collect(); - - let tags: Vec = tag::Entity::find() - .find_also_related(namespace::Entity) - .filter(tag::Column::Id.is_in(tag_ids)) - .all(&self.ctx.db) - .await? - .into_iter() - .map(map_tag_dto) - .collect(); - - let tag_id_map = tags - .into_iter() - .map(|t| (t.id(), t)) - .collect::>(); - let cd_tag_map = tag_cd_entries - .into_iter() - .filter_map(|(t, cd)| Some((cd?, tag_id_map.get(&t.tag_id)?.clone()))) - .sorted_by_key(|(cd, _)| cd.id) - .group_by(|(cd, _)| cd.descriptor.to_owned()) - .into_iter() - .map(|(key, group)| (key, group.map(|(_, t)| t).collect::>())) - .collect(); - - Ok(cd_tag_map) - } - #[tracing::instrument(level = "debug", skip(self))] pub async fn tags_for_cd(&self, cd_id: i64) -> RepoResult> { let tags = tag::Entity::find()