锈柴油orm查询

Posted

技术标签:

【中文标题】锈柴油orm查询【英文标题】:Rust diesel orm queries 【发布时间】:2021-03-17 09:27:27 【问题描述】:

我是生锈和柴油机的新手。我正在尝试对我的查询执行以下操作:

计数 选择 订购 限制

但我遇到了错误。 我正在使用 postgres 数据库。

我在评论中的查询上方添加了确切的错误。 这是我的代码:

schema.rs

table! 
    employee (employee_id) 
        employee_id -> Int4,
        name -> Nullable<Text>,
        age -> Nullable<Int4>,
        address -> Nullable<Text>,
        email -> Nullable<Text>,
        dept_id -> Int4,
        salary -> Nullable<Numeric>,
        created_on -> Nullable<Timestamp>,
        created_by -> Nullable<Text>,
        modified_on -> Nullable<Timestamp>,
        modified_by -> Nullable<Text>,
        is_active -> Nullable<Bool>,
    

models.rs

#![allow(unused)]
#![allow(clippy::all)]
use super::schema::employee;

use bigdecimal::BigDecimal;
use chrono::NaiveDateTime;

#[derive(Queryable, Debug, Identifiable)]
#[table_name = "employee"]
#[primary_key(employee_id)]
pub struct Employee 
    pub employee_id: i32,
    pub name: Option<String>,
    pub age: Option<i32>,
    pub address: Option<String>,
    pub email: Option<String>,
    pub dept_id: i32,
    pub salary: Option<BigDecimal>,
    pub created_on: Option<NaiveDateTime>,
    pub created_by: Option<String>,
    pub modified_on: Option<NaiveDateTime>,
    pub modified_by: Option<String>,
    pub is_active: Option<bool>,

cargo.toml

[dependencies]
diesel =  version = "1.4.5", features = ["postgres","chrono","numeric"] 
dotenv = "0.15.0"
chrono =  version = "0.4.19" , features = ["serde"] 
bigdecimal =  version = "0.1.0" 

ma​​in.rs

#[macro_use]
extern crate diesel;
extern crate bigdecimal;
extern crate chrono;
extern crate dotenv;

use crate::models::Employee;
use crate::models::Players;
use crate::schema::employee::dsl::*;

use diesel::pg::PgConnection, prelude::*;
use dotenv::dotenv;
use std::env;

mod models;
mod schema;

fn main() 
    dotenv().ok();
    let data_url: String = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let connection: PgConnection =
        PgConnection::establish(&data_url).expect(&format!("Error connect to ", data_url));

    //get all employees name
    //This is working fine
    let _employee: Vec<Employee> = employee
        .load::<Employee>(&connection)
        .expect("Error loading department");

    for emp in _employee 
        println!("", emp.name.unwrap_or_default());
    


    //----------------------------------------------
    //get employees count
    /*
    Error: error[E0282]: type annotations needed
           ^^^^^^^^^^^^^^^ consider giving `total_employees` a type
    */
    let total_employees = employee.count().get_result(&connection).expect("Error");
    println!("", total_employees);


    //-----------------------------------------------
     //get all names
    /*
        Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not satisfied
         ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let all_names = employee.select(name).load::<String>(&connection)?;
    println!("", all_names);


    //----------------------------------------------
    //order name
    /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not          satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let ordered_names = employee
        .select(name)
        .order(name.desc())
        .load::<String>(&connection)?;
    println!("", ordered_names);


   //------------------------------------------------
   /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not     satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
     */
    let limited = employee
        .select(name)
        .order(employee_id)
        .limit(1)
        .load::<String>(&connection)?;
    println!("", limited);

我错过了什么吗? 有人可以纠正我吗? 谢谢!

【问题讨论】:

【参考方案1】:

首先:您的代码缺少实际重现那里描述的问题的关键信息。在不知道您的底层数据库架构的情况下,只能猜测它的样子。对于我的回答,我将假设以下架构:

table! 
    employee(employee_id) 
        employee_id -> Integer,
        name -> Nullable<Text>,
        age -> Nullable<Integer>,
        address -> Nullable<Text>,
        email -> Nullable<Text>,
        dept_id -> Integer,
        salary -> Nullable<Numeric>,
        created_on -> Nullable<Timestamp>,
        created_by -> Nullable<Text>,
        modified_on -> Nullable<Timestamp>,
        modified_by -> Nullable<Text>,
        is_active -> Nullable<Bool>,
    

现在作为一般规则:Diesel 将此定义用作事实来源,并且仅支持某些类型映射。如果您遇到编译错误,这可能意味着以下情况之一是错误的:

您已尝试将查询结果映射到包含某些返回列的不兼容字段的结构 您尝试将查询结果映射到包含比查询返回的更多或更少字段的结构

回答您的具体错误信息:

    //----------------------------------------------
    //get employees count
    /*
    Error: error[E0282]: type annotations needed
           ^^^^^^^^^^^^^^^ consider giving `total_employees` a type
    */
    let total_employees = employee.count().get_result(&connection).expect("Error");
    println!("", total_employees);

Rustc 需要知道total_employees 的类型,因为get_result 返回一个泛型类型,而println 使用一个泛型类型。 Rustc 需要确切地知道应该在那里使用哪种类型。现在柴油文档在正确的返回类型上有点稀疏,但Daniel Porteous 中的错误消息表明此查询返回一个BigInt,它与i64 兼容,如here 所述。这意味着这个查询可以工作:

    let total_employees: i64 = employee.count().get_result(&connection).expect("Error");

接下来的三个查询基本上无法编译并出现相同的错误消息:


    //-----------------------------------------------
     //get all names
    /*
        Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not satisfied
         ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let all_names = employee.select(name).load::<String>(&connection)?;
    println!("", all_names);


    //----------------------------------------------
    //order name
    /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not          satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let ordered_names = employee
        .select(name)
        .order(name.desc())
        .load::<String>(&connection)?;
    println!("", ordered_names);


   //------------------------------------------------
   /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not     satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
     */
    let limited = employee
        .select(name)
        .order(employee_id)
        .limit(1)
        .load::<String>(&connection)?;
    println!("", limited);

现在,此错误消息表明您尝试将查询返回的字段映射到 rust 端的不兼容类型。在这种情况下,不支持将不是NOT NULLText 字段映射到String,因为在这种情况下柴油如何表示NULL 值。 documentation states 需要将可空类型包装在 Option 生锈方面。这意味着如果您在所有情况下将返回类型更改为Option&lt;String&gt;,一切都会成功编译。

【讨论】:

你说得对。我的架构与您上面提到的相同。我还编辑了这个问题,现在它有“schema.rs”。对不起,我错过了。 改变返回类型!!!你的意思是说我的其他查询应该像这样“让 all_names: Option = employee.select(name).load::(&connection)?;”这用于限制: let limited: Option = employee .select(name) .order(employee_id) .limit(1) .load::(&connection)?;你说的是这种方式吗? 更改返回类型是指更改这些查询返回的类型。您已经在.load 上使用turbofish 语法设置了它们,所以只需将.load::&lt;String&gt;(&amp;connection)? 更改为.load::&lt;Option&lt;String&gt;&gt;(&amp;connection)? 解释问题很有帮助,谢谢@weiznich【参考方案2】:
let total_employees = employee.count().get_result(&connection).expect("Error");

对于这个,尝试注释total_employees,如下所示:

let total_employees: u64 = employee.count().get_result(&connection).expect("Error");

这将帮助您继续。即使函数没有返回这样的类型,错误现在至少会告诉你它是什么类型。

【讨论】:

我注意到加载你的员工,你使用涡轮鱼,比如.load::&lt;Employee&gt;()count() 你也需要那个吗? 它不工作。我仍然收到错误“^^^^^^^^^^ 特征 FromSql&lt;diesel::sql_types::BigInt, Pg&gt; 没有为 u64 实现” 这个答案具有误导性,因为 u64 不是柴油支持的类型(正如错误消息告诉你的那样) 答案很有帮助,因为现在提问者知道他们需要使用 BigInt。一般的建议是添加一个类型注释,让编译器告诉你你正在使用什么类型。

以上是关于锈柴油orm查询的主要内容,如果未能解决你的问题,请参考以下文章

无法在锈柴油中使用通用参数实现特征

是否可以在柴油中使用没有主键的表?锈

如何选择带有柴油 rs 的列子集?

柴油查询中的“听起来像”

如何使用柴油进行 IN 查询?

在柴油机中执行正确连接