diff --git a/das_api/src/api/api_impl.rs b/das_api/src/api/api_impl.rs index 477b1576c..d32f3c880 100644 --- a/das_api/src/api/api_impl.rs +++ b/das_api/src/api/api_impl.rs @@ -300,6 +300,7 @@ impl ApiContract for DasApi { page, before, after, + json_uri, } = payload; // Deserialize search assets query self.validate_pagination(&limit, &page, &before, &after)?; @@ -348,6 +349,7 @@ impl ApiContract for DasApi { royalty_target, royalty_amount, burnt, + json_uri, }; let sort_by = sort_by.unwrap_or_default(); let transform = AssetTransform { diff --git a/das_api/src/api/mod.rs b/das_api/src/api/mod.rs index c9cd8ed79..38a6e5850 100644 --- a/das_api/src/api/mod.rs +++ b/das_api/src/api/mod.rs @@ -79,6 +79,8 @@ pub struct SearchAssets { pub page: Option, pub before: Option, pub after: Option, + #[serde(default)] + pub json_uri: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] diff --git a/digital_asset_types/src/dao/mod.rs b/digital_asset_types/src/dao/mod.rs index abe40b2f1..673a7559a 100644 --- a/digital_asset_types/src/dao/mod.rs +++ b/digital_asset_types/src/dao/mod.rs @@ -53,6 +53,7 @@ pub struct SearchAssetsQuery { pub royalty_target: Option>, pub royalty_amount: Option, pub burnt: Option, + pub json_uri: Option, } impl SearchAssetsQuery { @@ -111,6 +112,9 @@ impl SearchAssetsQuery { if self.grouping.is_some() { num_conditions += 1; } + if self.json_uri.is_some() { + num_conditions += 1; + } num_conditions } @@ -223,6 +227,21 @@ impl SearchAssetsQuery { joins.push(rel); } + if let Some(ju) = self.json_uri.to_owned() { + let cond = Condition::all() + .add(asset_data::Column::MetadataUrl.eq(ju)); + conditions = conditions.add(cond); + let rel = asset_data::Relation::Asset + .def() + .rev() + .on_condition(|left, right| { + Expr::tbl(right, asset_data::Column::Id) + .eq(Expr::tbl(left, asset::Column::AssetData)) + .into_condition() + }); + joins.push(rel); + } + Ok(( match self.negate { None | Some(false) => conditions, diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index fdba3b846..18f2467c5 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -4,6 +4,7 @@ use crate::dao::{ }; use indexmap::IndexMap; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; +use std::collections::HashMap; pub fn paginate<'db, T>(pagination: &Pagination, limit: u64, stmt: T) -> T where @@ -156,7 +157,6 @@ where E: RelationTrait, { let mut stmt = asset::Entity::find() - .find_also_related(asset_data::Entity) .filter(condition) .join(JoinType::LeftJoin, relation.def()) .order_by(sort_by, sort_direction); @@ -170,27 +170,39 @@ where pub async fn get_related_for_assets( conn: &impl ConnectionTrait, - assets: Vec<(asset::Model, Option)>, + assets: Vec, ) -> Result, DbErr> { - let mut ids = Vec::with_capacity(assets.len()); + let asset_ids = assets.iter().map(|a| a.id.clone()).collect::>(); + + let asset_data: Vec = asset_data::Entity::find() + .filter(asset_data::Column::Id.is_in(asset_ids)) + .all(conn) + .await?; + let asset_data_map = asset_data.into_iter().fold(HashMap::new(), |mut acc, ad| { + acc.insert(ad.id.clone(), ad); + acc + }); + // Using IndexMap to preserve order. - let mut assets_map = assets.into_iter().fold(IndexMap::new(), |mut x, asset| { - if let Some(ad) = asset.1 { - let id = asset.0.id.clone(); + let mut assets_map = assets.into_iter().fold(IndexMap::new(), |mut acc, asset| { + if let Some(ad) = asset + .asset_data + .clone() + .and_then(|ad_id| asset_data_map.get(&ad_id)) + { + let id = asset.id.clone(); let fa = FullAsset { - asset: asset.0, - data: ad, + asset: asset, + data: ad.clone(), authorities: vec![], creators: vec![], groups: vec![], }; - - x.insert(id.clone(), fa); - ids.push(id); - } - x + acc.insert(id, fa); + }; + acc }); - + let ids = assets_map.keys().cloned().collect::>(); let authorities = asset_authority::Entity::find() .filter(asset_authority::Column::AssetId.is_in(ids.clone())) .order_by_asc(asset_authority::Column::AssetId) @@ -243,7 +255,7 @@ pub async fn get_assets_by_condition( stmt = stmt.filter(condition).order_by(sort_by, sort_direction); stmt = paginate(pagination, limit, stmt); - let asset_list = stmt.find_also_related(asset_data::Entity).all(conn).await?; + let asset_list = stmt.all(conn).await?; get_related_for_assets(conn, asset_list).await }