leetcode_api/dao/
query.rs

1use miette::{IntoDiagnostic, Result};
2use sea_orm::{
3    ColumnTrait, EntityTrait, FromQueryResult, QueryFilter, QuerySelect, sea_query::Expr,
4};
5use tracing::debug;
6
7use super::{detail, glob_db, index};
8use crate::{
9    entities::{new_index, prelude::*, topic_tags},
10    leetcode::IdSlug,
11};
12
13#[derive(Clone, Copy)]
14#[derive(Debug)]
15#[derive(Default)]
16#[derive(PartialEq, Eq, PartialOrd, Ord)]
17pub struct Query;
18
19#[derive(FromQueryResult)]
20#[derive(Debug)]
21#[derive(Clone)]
22pub struct PassStat {
23    pub diff: String,
24    pub pass_count: u32,
25    pub sum: u32,
26}
27
28impl Query {
29    /// Find the problem, return one
30    ///
31    /// * `idslug`: id or title
32    pub async fn get_question_index(idslug: &IdSlug) -> Result<index::Model> {
33        let res = match idslug {
34            IdSlug::Id(id) => Index::find_by_id(*id)
35                .one(glob_db().await)
36                .await
37                .into_diagnostic()?
38                .unwrap_or_default(),
39            IdSlug::Slug(slug) => Index::find()
40                .filter(index::Column::QuestionTitleSlug.eq(slug))
41                .one(glob_db().await)
42                .await
43                .into_diagnostic()?
44                .unwrap_or_default(),
45        };
46        debug!("get value {:#?}", res);
47        Ok(res)
48    }
49
50    pub async fn query_detail_by_id(id: u32) -> Result<Option<detail::Model>> {
51        Detail::find_by_id(id)
52            .one(glob_db().await)
53            .await
54            .into_diagnostic()
55    }
56
57    pub async fn query_all_index() -> Result<Vec<index::Model>> {
58        let models = Index::find()
59            .all(glob_db().await)
60            .await
61            .into_diagnostic()?;
62
63        Ok(models)
64    }
65    pub async fn query_by_topic(
66        topic_slugs: &[String],
67        difficulty: Option<String>,
68    ) -> Result<Vec<new_index::Model>> {
69        let mut cond = topic_tags::Column::TopicSlug.is_in(topic_slugs);
70
71        if let Some(v) = difficulty {
72            if !v.is_empty() {
73                cond = cond.and(new_index::Column::Difficulty.eq(v));
74            }
75        }
76
77        NewIndexDB::find()
78            .inner_join(topic_tags::Entity)
79            .filter(cond)
80            .group_by(new_index::Column::TitleSlug)
81            .having(
82                topic_tags::Column::TopicSlug
83                    .count()
84                    .eq(topic_slugs.len() as i32),
85            )
86            .all(glob_db().await)
87            .await
88            .into_diagnostic()
89    }
90
91    pub async fn query_status() -> Result<Vec<PassStat>> {
92        NewIndexDB::find()
93            .select_only()
94            .column_as(new_index::Column::Difficulty, "diff")
95            .column_as(
96                Expr::expr(new_index::Column::Status.eq("AC")).sum(),
97                "pass_count",
98            )
99            .column_as(new_index::Column::TitleSlug.count(), "sum")
100            .group_by(new_index::Column::Difficulty)
101            .into_model::<PassStat>()
102            .all(glob_db().await)
103            .await
104            .into_diagnostic()
105    }
106
107    pub async fn query_all_topic() -> Result<Vec<topic_tags::Model>> {
108        TopicTagsDB::find()
109            .all(glob_db().await)
110            .await
111            .into_diagnostic()
112    }
113
114    pub async fn query_all_new_index<D>(diff: D) -> Result<Vec<new_index::Model>>
115    where
116        D: Into<Option<String>> + Send,
117    {
118        if let Some(diff) = diff.into() {
119            if !diff.is_empty() {
120                return NewIndexDB::find()
121                    .filter(new_index::Column::Difficulty.eq(diff))
122                    .all(glob_db().await)
123                    .await
124                    .into_diagnostic();
125            }
126        }
127        NewIndexDB::find()
128            .all(glob_db().await)
129            .await
130            .into_diagnostic()
131    }
132}