Clickhouse兼容Rust的官网有三种方式,以下方式是唯一可以调通的,希望对大家有帮助
use core::panic;
use actix_http::Request;
use chrono::Utc;
use futures::StreamExt;
use klickhouse::*;
use std::collections::HashMap;
use std::collections::HashSet;
use actix_web::*;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tracing::{error, info};
use crate::error::{RecloudError, StandardResp};
use crate::server;
use super::super::AppState;
use klickhouse::{Client, Row};
pub async fn query<T: Row>(sql: &str, client: &Client) -> anyhow::Result<Option<Vec<T>>> {
let mut result = Vec::new();
let mut rows = client.query::<T>(sql).await?;
while let Some(row) = rows.next().await {
result.push(row?);
}
if result.len() == 0 {
return Ok(None);
}
Ok(Some(result))
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Resp {
pub data: Vec<Option<Vec<ChRes>>>,
}
#[derive(Debug, Serialize, Deserialize, Row, Clone)]
pub struct ChRes {
pub carno: String,
pub mile: f64,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct CkData {
car_no_list: Vec<String>,
durations: Vec<Vec<String>>,
}
#[post("/get_ck_info")]
pub async fn get_ck_info(
request: web::Json<CkData>,
) -> std::result::Result<HttpResponse, RecloudError> {
let tmp = (1, "", true);
println!("{:?}", tmp.1);
info!("inside get_ck_info");
let client = Client::connect("172.16.xxx.xx:9000", ClientOptions::default())
.await
.unwrap();
let car_no_list = request
.car_no_list
.iter()
.map(|carno: &String| format!("'{}'", carno))
.collect::<Vec<_>>()
.join(",");
let mut res_map: HashMap<String, Vec<f64>> = HashMap::new();
let carno = request.car_no_list[0].clone();
let mut res_list: Vec<f64> = vec![];
for duration in &request.durations {
let sql = format!(
r#"select carno,
max(acc_power_left) - min(acc_power_left) as mile
from table
where carno in ({})
and car_time >= '{}'
and car_time <= '{}'
group by carno
"#,
car_no_list, duration[0], duration[1]
);
let res = query::<ChRes>(&sql, &client).await;
match res {
Ok(Some(vec)) => {
info!("{:?}", vec);
res_list.extend(vec.iter().map(|r| r.mile.clone()).collect::<Vec<f64>>());
}
Ok(None) => {
println!("Option is None");
}
Err(e) => return Err(RecloudError::QueryError),
}
}
res_map.insert(carno.clone(), res_list);
Ok(HttpResponse::Ok().json(StandardResp::success(Some(json!(res_map)))))
}
pub fn get_ck_info_api() -> Scope {
web::scope("").service(get_ck_info)
}