diff --git a/src/area/service.rs b/src/area/service.rs index 05ead5e..2f10ede 100644 --- a/src/area/service.rs +++ b/src/area/service.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use super::Area; use crate::{ element::{self, Element}, + element_comment::ElementComment, event::Event, Error, Result, }; @@ -111,6 +112,7 @@ pub struct TrendingArea { pub created: i64, pub updated: i64, pub deleted: i64, + pub comments: i64, } pub fn get_trending_areas( @@ -124,6 +126,10 @@ pub fn get_trending_areas( .into_iter() .filter(|it| it.deleted_at == None) .collect(); + let elements: Vec = Element::select_all(None, &conn)? + .into_iter() + .filter(|it| it.deleted_at == None) + .collect(); let mut areas_to_events: HashMap> = HashMap::new(); for area in &areas { areas_to_events.insert(area.id, vec![]); @@ -152,12 +158,11 @@ pub fn get_trending_areas( area_events.push(event); } } - let mut trending_areas: Vec<_> = areas_to_events + let trending_areas: Vec<_> = areas_to_events .into_iter() .map(|it| (Area::select_by_id(it.0, &conn).unwrap().unwrap(), it.1)) .collect(); - trending_areas.sort_by(|x, y| y.1.len().cmp(&x.1.len())); - Ok(trending_areas + let mut res: Vec = trending_areas .into_iter() .filter(|it| it.0.tags.contains_key("type") && it.0.tags["type"].as_str() == Some(r#type)) .map(|it| { @@ -172,6 +177,11 @@ pub fn get_trending_areas( _ => {} } } + let comments: Vec = get_comments(&it.0, &elements, conn) + .unwrap() + .into_iter() + .filter(|it| &it.created_at > period_start && &it.created_at < period_end) + .collect(); TrendingArea { id: it.0.id, name: it.0.name(), @@ -180,9 +190,31 @@ pub fn get_trending_areas( created: created.len() as i64, updated: updated.len() as i64, deleted: deleted.len() as i64, + comments: comments.len() as i64, } }) - .collect()) + .filter(|it| it.events + it.comments != 0) + .collect(); + res.sort_by(|a, b| { + (b.created + b.updated + b.deleted + b.comments) + .cmp(&(a.created + a.updated + a.deleted + a.comments)) + }); + Ok(res) +} + +fn get_comments( + area: &Area, + all_elements: &Vec, + conn: &Connection, +) -> Result> { + let area_elements = element::service::filter_by_area_quick(&all_elements, area)?; + let mut comments: Vec = vec![]; + for element in area_elements { + for comment in ElementComment::select_by_element_id(element.id, conn)? { + comments.push(comment); + } + } + Ok(comments) } #[cfg(test)] diff --git a/src/element/service.rs b/src/element/service.rs index 41aae68..e5a4885 100644 --- a/src/element/service.rs +++ b/src/element/service.rs @@ -82,6 +82,21 @@ pub fn filter_by_area(all_elements: &Vec, area: &Area) -> Result, area: &Area) -> Result> { + let mut area_elements: Vec = vec![]; + for element in all_elements { + if element.tag("areas").is_array() { + let element_areas = element.tag("areas").as_array().unwrap(); + for element_area in element_areas { + if element_area["id"].as_i64().unwrap() == area.id { + area_elements.push(element.clone()); + } + } + } + } + Ok(area_elements) +} + pub fn update_areas_tag(elements: &Vec, conn: &Connection) -> Result> { let mut res: Vec = vec![]; diff --git a/src/element_comment/model.rs b/src/element_comment/model.rs index 9345766..09e4a58 100644 --- a/src/element_comment/model.rs +++ b/src/element_comment/model.rs @@ -92,6 +92,28 @@ impl ElementComment { Ok(res) } + pub fn select_by_element_id(element_id: i64, conn: &Connection) -> Result> { + let query = format!( + r#" + SELECT {ALL_COLUMNS} + FROM {TABLE} + WHERE {COL_ELEMENT_ID} = :element_id + ORDER BY {COL_UPDATED_AT}, {COL_ID} + "# + ); + debug!(query); + let res = conn + .prepare(&query)? + .query_map( + named_params! { + ":element_id": element_id, + }, + mapper(), + )? + .collect::, _>>()?; + Ok(res) + } + pub fn select_by_id(id: i64, conn: &Connection) -> Result> { let query = format!( r#" diff --git a/src/event/model.rs b/src/event/model.rs index 9fa2b28..987c97e 100644 --- a/src/event/model.rs +++ b/src/event/model.rs @@ -6,9 +6,11 @@ use rusqlite::OptionalExtension; use rusqlite::Row; use serde_json::Value; use std::collections::HashMap; +use std::time::Instant; use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; use tracing::debug; +use tracing::info; #[derive(Debug, Eq, PartialEq)] pub struct Event { @@ -142,6 +144,7 @@ impl Event { period_end: &OffsetDateTime, conn: &Connection, ) -> Result> { + let start = Instant::now(); let query = format!( r#" SELECT @@ -162,7 +165,7 @@ impl Event { "# ); debug!(query); - Ok(conn + let res = conn .prepare(&query)? .query_map( named_params! { @@ -171,7 +174,16 @@ impl Event { }, mapper(), )? - .collect::, _>>()?) + .collect::, _>>()?; + let time_ms = start.elapsed().as_millis(); + info!( + count = res.len(), + time_ms, + "Loaded {} events in {} ms", + res.len(), + time_ms, + ); + Ok(res) } pub fn select_by_id(id: i64, conn: &Connection) -> Result> { diff --git a/src/server/mod.rs b/src/server/mod.rs index 7e4a727..f798852 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -92,7 +92,10 @@ pub async fn run() -> Result<()> { .with_method("setareatag", rpc::set_area_tag::run) .with_method("removeareatag", rpc::remove_area_tag::run) .with_method("gettrendingcountries", rpc::get_trending_countries::run) - .with_method("getmostcommentedcountries", rpc::get_most_commented_countries::run) + .with_method( + "getmostcommentedcountries", + rpc::get_most_commented_countries::run, + ) .with_method("gettrendingcommunities", rpc::get_trending_communities::run) .with_method("removearea", rpc::remove_area::run) .finish()