diesel: inner_join 转发查询
diesel: inner_join forward query
我正在学习使用inner_join进行正向查询
pub async fn hello(pool: web::Data<DbPool>) -> HttpResult {
let conn = pool.get().map_err(ErrorInternalServerError)?;
let data: Vec<(models::Book, models::User)> = books::table
.inner_join(users::table)
.load::<(models::Book, models::User)>(&conn)
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(data))
}
我得到了正确的数据
[
[{
"id": 1,
"name": "js",
"user_id": 1
}, {
"id": 1,
"username": "admin"
}],
[{
"id": 2,
"name": "rust",
"user_id": 1
}, {
"id": 1,
"username": "admin"
}]
]
但是这个json数据的结构不是我想要的
我想要这个嵌套结构
[{
"id": 1,
"name": "js",
"user": {
"id": 1,
"username": "admin"
}
}, {
"id": 2,
"name": "rust",
"user": {
"id": 1,
"username": "admin"
}
}]
我不知道如何转换,有没有最佳实践
更多信息
架构:
table! {
books (id) {
id -> Unsigned<Bigint>,
name -> Varchar,
user_id -> Unsigned<Bigint>,
}
}
table! {
users (id) {
id -> Unsigned<Bigint>,
username -> Varchar,
}
}
joinable!(books -> users (user_id));
allow_tables_to_appear_in_same_query!(
books,
users,
);
型号:
#[derive(Identifiable, Queryable, Associations, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(User, foreign_key = "user_id")]
#[table_name = "books"]
pub struct Book {
#[serde(skip_deserializing)]
pub id: PK,
pub name: String,
pub user_id: PK,
}
#[derive(Identifiable, Queryable, Serialize, Deserialize, Debug, Clone)]
#[table_name = "users"]
pub struct User {
pub id: PK,
pub username: String,
}
柴油版
diesel = { version = "1.4.4", features = ["mysql", "r2d2", "chrono", "numeric"] }
你真正的问题是 serde
crate
如果您有这样的数据类型 (String, i32, ...)
serde
将在输出中创建数组,请参见以下代码
fn main() {
let val = ("Hello", 123, 2.5);
let result = serde_json::to_string(&val).unwrap();
println!("{}", result); // ["Hello",123,2.5]
}
所以如果你想解决它,你可以这样做
首先制作您的自定义模型
struct User {
id: i32,
username: String,
}
struct ResponseModel {
id: i32,
name: String,
user: User,
}
现在为 ResponseModel
实施 From
特征
impl From<(models::Book, models::User)> for ResponseModel {
fn from(values: (models::Book, models::User)) -> Self {
Self {
id: values.0.id,
name: values.0.name,
user: User {
id: values.1.id,
username: values.1.username,
},
}
}
}
现在像这样更改 hello
fn
pub async fn hello(pool: web::Data<DbPool>) -> HttpResult {
let conn = pool.get().map_err(ErrorInternalServerError)?;
let data: Vec<ResponseModel> = books::table
.inner_join(users::table)
.load::<(models::Book, models::User)>(&conn)
.map(|x| x.into_iter().map(ResponseModel::from).collect())
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(data))
}
一个简单的方法是使用 #[serde(flatten)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BookWithUser<B, U> {
#[serde(flatten)]
book: B,
user: U,
}
impl<B, U> From<(B, U)> for BookWithUser<B, U> {
fn from((b, u): (B, U)) -> Self {
Self { book: b, user: u }
}
}
#[derive(Identifiable, Associations, Queryable, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(models::user::User, foreign_key = "user_id")]
#[table_name = "books"]
pub struct Book {
...
}
然后像这样使用
#[get("/with_user")]
pub async fn list_with_user(pool: web::Data<DbPool>) -> HttpResult {
use schema::*;
let res = web::block(move || -> Result<_, DbError> {
let conn = pool.get()?;
let res = books::table
.inner_join(users::table)
.load::<(mods::book::Book, mods::user::User)>(&conn)
.map(|x| x.into_iter().map(mods::book::BookWithUser::from))?
.collect::<Vec<_>>();
Ok(res)
})
.await?
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(res))
}
我正在学习使用inner_join进行正向查询
pub async fn hello(pool: web::Data<DbPool>) -> HttpResult {
let conn = pool.get().map_err(ErrorInternalServerError)?;
let data: Vec<(models::Book, models::User)> = books::table
.inner_join(users::table)
.load::<(models::Book, models::User)>(&conn)
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(data))
}
我得到了正确的数据
[
[{
"id": 1,
"name": "js",
"user_id": 1
}, {
"id": 1,
"username": "admin"
}],
[{
"id": 2,
"name": "rust",
"user_id": 1
}, {
"id": 1,
"username": "admin"
}]
]
但是这个json数据的结构不是我想要的
我想要这个嵌套结构
[{
"id": 1,
"name": "js",
"user": {
"id": 1,
"username": "admin"
}
}, {
"id": 2,
"name": "rust",
"user": {
"id": 1,
"username": "admin"
}
}]
我不知道如何转换,有没有最佳实践
更多信息
架构:
table! {
books (id) {
id -> Unsigned<Bigint>,
name -> Varchar,
user_id -> Unsigned<Bigint>,
}
}
table! {
users (id) {
id -> Unsigned<Bigint>,
username -> Varchar,
}
}
joinable!(books -> users (user_id));
allow_tables_to_appear_in_same_query!(
books,
users,
);
型号:
#[derive(Identifiable, Queryable, Associations, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(User, foreign_key = "user_id")]
#[table_name = "books"]
pub struct Book {
#[serde(skip_deserializing)]
pub id: PK,
pub name: String,
pub user_id: PK,
}
#[derive(Identifiable, Queryable, Serialize, Deserialize, Debug, Clone)]
#[table_name = "users"]
pub struct User {
pub id: PK,
pub username: String,
}
柴油版
diesel = { version = "1.4.4", features = ["mysql", "r2d2", "chrono", "numeric"] }
你真正的问题是 serde
crate
如果您有这样的数据类型 (String, i32, ...)
serde
将在输出中创建数组,请参见以下代码
fn main() {
let val = ("Hello", 123, 2.5);
let result = serde_json::to_string(&val).unwrap();
println!("{}", result); // ["Hello",123,2.5]
}
所以如果你想解决它,你可以这样做
首先制作您的自定义模型
struct User {
id: i32,
username: String,
}
struct ResponseModel {
id: i32,
name: String,
user: User,
}
现在为 ResponseModel
From
特征
impl From<(models::Book, models::User)> for ResponseModel {
fn from(values: (models::Book, models::User)) -> Self {
Self {
id: values.0.id,
name: values.0.name,
user: User {
id: values.1.id,
username: values.1.username,
},
}
}
}
现在像这样更改 hello
fn
pub async fn hello(pool: web::Data<DbPool>) -> HttpResult {
let conn = pool.get().map_err(ErrorInternalServerError)?;
let data: Vec<ResponseModel> = books::table
.inner_join(users::table)
.load::<(models::Book, models::User)>(&conn)
.map(|x| x.into_iter().map(ResponseModel::from).collect())
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(data))
}
一个简单的方法是使用 #[serde(flatten)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BookWithUser<B, U> {
#[serde(flatten)]
book: B,
user: U,
}
impl<B, U> From<(B, U)> for BookWithUser<B, U> {
fn from((b, u): (B, U)) -> Self {
Self { book: b, user: u }
}
}
#[derive(Identifiable, Associations, Queryable, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(models::user::User, foreign_key = "user_id")]
#[table_name = "books"]
pub struct Book {
...
}
然后像这样使用
#[get("/with_user")]
pub async fn list_with_user(pool: web::Data<DbPool>) -> HttpResult {
use schema::*;
let res = web::block(move || -> Result<_, DbError> {
let conn = pool.get()?;
let res = books::table
.inner_join(users::table)
.load::<(mods::book::Book, mods::user::User)>(&conn)
.map(|x| x.into_iter().map(mods::book::BookWithUser::from))?
.collect::<Vec<_>>();
Ok(res)
})
.await?
.map_err(ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(res))
}