左连接在生 rust 的柴油

ohtdti5x  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(169)

我的PostgreSQL数据库中有书籍数据。我需要获取每本书的最后一章。我需要书籍章节中有关Null值的信息。这就是为什么我使用左连接。

#[derive(Associations, Identifiable, Queryable,
         PartialEq, Debug, Deserialize, Serialize)]
#[diesel(belongs_to(User))]
#[diesel(table_name = books)]
pub struct Book {
    pub id: i32,
    pub user_id: i32,
    pub title: String,
    pub book_description: String,
    pub normalize_book_title: String,    
    pub book_image: Option<String>,
    pub publish_day: chrono::NaiveDateTime,
}

#[derive(Associations, Identifiable, Queryable,
         PartialEq, Debug, Deserialize, Serialize)]
#[diesel(belongs_to(Book))]
#[diesel(table_name = book_chapters)]
pub struct BookChapter {
    pub id: i32,
    pub book_id: i32,
    pub title: String,
    pub normalize_title: String,
    pub body: String,
    pub description: String,
    pub publish_day: chrono::NaiveDateTime,
}

diesel::table! {
    books (id) {
        id -> Int4,
        user_id -> Int4,
        title -> Varchar,
        book_description -> Varchar,
        normalize_book_title -> Varchar,
        book_image -> Nullable<Varchar>,
        publish_day -> Timestamp,
    }
}

diesel::table! {
    book_chapters (id) {
        id -> Int4,
        book_id -> Int4,
        title -> Varchar,
        normalize_title -> Varchar,
        body -> Text,
        description -> Varchar,        
        publish_day -> Timestamp,
    }
}

diesel::joinable!(book_chapters -> books (book_id));
diesel::allow_tables_to_appear_in_same_query!(books, book_chapters);

我在Actix中的代码:

pub fn get_all_books_with_last_chapters_left_join(db_connection: &mut PgConnection) -> Result<Vec<(String, String)>, DieselError> {
        let result = books::table.left_join(book_chapters::table)
                    .select((book::title.nullable(), chapter::title.nullable()))
                    .load(db_connection);
        result
    }

我在不同的地方有异常处理。
我的代码引发了一个异常:

error[E0277]: the trait bound `(std::string::String, std::string::String): FromStaticSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not satisfied
    --> database/src/database_manager.rs:126:27
     |
126  |                     .load(db_connection);
     |                      ---- ^^^^^^^^^^^^^ the trait `FromStaticSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not implemented for `(std::string::String, std::string::String)`
     |                      |
     |                      required by a bound introduced by this call
     |
     = help: the following other types implement trait `FromStaticSqlRow<ST, DB>`:
               <(T0,) as FromStaticSqlRow<(ST0,), __DB>>
               <(T1, T0) as FromStaticSqlRow<(ST1, ST0), __DB>>
               <(T1, T2, T0) as FromStaticSqlRow<(ST1, ST2, ST0), __DB>>
               <(T1, T2, T3, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST0), __DB>>
               <(T1, T2, T3, T4, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST0), __DB>>
             and 24 others
     = note: required for `(std::string::String, std::string::String)` to implement `diesel::Queryable<(diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>`
     = note: required for `(std::string::String, std::string::String)` to implement `FromSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>`
     = note: required for `(diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Text>)` to implement `load_dsl::private::CompatibleType<(std::string::String, std::string::String), Pg>`
     = note: required for `SelectStatement<FromClause<JoinOn<Join<table, table, LeftOuter>, Grouped<Eq<Nullable<book_id>, Nullable<id>>>>>, SelectClause<(Nullable<title>, Nullable<title>)>>` to implement `LoadQuery<'_, PgConnection, (std::string::String, std::string::String)>`
     = note: the full type name has been written to '/home/redbeardman/Development/ActixWeb/blog_site/target/debug/deps/database-ab8567b4f90f5964.long-type-17256427855449653182.txt'
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/redbeardman/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.3/src/query_dsl/mod.rs:1499:15
     |
1499 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`

For more information about this error, try `rustc --explain E0277`.

我该怎么补救呢?
我的工作inner_join:

pub fn get_all_books_with_last_chapters(db_connection: &mut PgConnection) -> Result<Vec<(String, String)>, DieselError> {
        let result: Result<Vec<(String, String)>,
                           diesel::result::Error> = books::table.inner_join(book_chapters::table)
                    .select((book::title, chapter::title))
                    .load(db_connection);
        result
    }
mklgxw1f

mklgxw1f1#

这看起来是一个简单的类型不匹配。您已经指定.select中的类型应该是.nullable(),这意味着这些列的Diesel-SQL类型是Nullable<Text>,但您只将它们加载为String s,这是不兼容的;NULL的值是多少?
从查询中,你应该总是有一个book::title,但可能没有一个chapter::title。所以你的选择和类型应该反映这一点。试试这个:

pub fn get_all_books_with_last_chapters_left_join(
    db_connection: &mut PgConnection,
) -> Result<Vec<(String, Option<String>)>, DieselError> {
                      // ^^^^^^^^^^^^^^
    let result = books::table
        .left_join(book_chapters::table)
        .select((book::title, chapter::title.nullable()))
              // ^^^^^^^^^^^
        .load(db_connection);

    result
}

相关问题