From d085935b7ee47f14bc9e8e4be1a6f5f805f5f8a6 Mon Sep 17 00:00:00 2001 From: Linus Kendall Date: Thu, 22 Jun 2023 01:00:23 +0530 Subject: [PATCH] feat(das-api): support searching assets by `jsonUri` parameter (#79) (#78) * feat(das-api): support searching assets by `jsonUri` parameter (#79) * add dto parameter * add dao condition * upd asset_data fetching to ensure single presence of asset_data in query * use asset.asset_data key for linking between asset/asset_data * fix: breaking arg order for array queries * chore: consistent arg order in `SearchAssets` destructuring * fix: breaking arg count for array params in searchAssets * Cargo fmt --------- Co-authored-by: Alex Tsymbal --- das_api/src/api/api_impl.rs | 2 + das_api/src/api/mod.rs | 3 +- digital_asset_types/src/dao/mod.rs | 18 +++++++++ digital_asset_types/src/dao/scopes/asset.rs | 43 +++++++++++++-------- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/das_api/src/api/api_impl.rs b/das_api/src/api/api_impl.rs index 06119b16d..daa4fa81a 100644 --- a/das_api/src/api/api_impl.rs +++ b/das_api/src/api/api_impl.rs @@ -274,6 +274,7 @@ impl ApiContract for DasApi { page, before, after, + json_uri } = payload; // Deserialize search assets query self.validate_pagination(&limit, &page, &before, &after)?; @@ -322,6 +323,7 @@ impl ApiContract for DasApi { royalty_target, royalty_amount, burnt, + json_uri, }; let sort_by = sort_by.unwrap_or_default(); // Execute query diff --git a/das_api/src/api/mod.rs b/das_api/src/api/mod.rs index 1c7550e81..05ff74536 100644 --- a/das_api/src/api/mod.rs +++ b/das_api/src/api/mod.rs @@ -79,11 +79,12 @@ 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)] #[serde(rename_all = "camelCase")] - pub struct GetAssetsByAuthority { pub authority_address: String, pub sort_by: Option, diff --git a/digital_asset_types/src/dao/mod.rs b/digital_asset_types/src/dao/mod.rs index 3bf48622c..ee78c6833 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,20 @@ 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 392b3939e..46bd57d18 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -3,7 +3,7 @@ use crate::dao::{ Pagination, }; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; pub fn paginate(pagination: &Pagination, limit: u64, stmt: T) -> T where @@ -156,7 +156,6 @@ where E: RelationTrait, { let mut stmt = asset::Entity::find() - .find_also_related(asset_data::Entity) .filter(condition) .join(JoinType::LeftJoin, relation.def()) .distinct_on([(asset::Entity, asset::Column::Id)]) @@ -172,27 +171,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 BTreeMap to preserve order. - let mut assets_map = assets.into_iter().fold(BTreeMap::new(), |mut x, asset| { - if let Some(ad) = asset.1 { - let id = asset.0.id.clone(); + let mut assets_map = assets.into_iter().fold(BTreeMap::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) @@ -248,7 +259,7 @@ pub async fn get_assets_by_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 }