postgresql - 如何使用 diesel-rs 选择部分色谱柱?

标签 postgresql rust rust-diesel

我现在正在努力几个小时来查询表的可用列的子集,并在其中包含一个计算。我知道这不是在选择查询中执行计算的最佳方式,但目前,我只是在研究原型(prototype),它应该是可行的。

我正在使用 diesel-rs作为我后端实现中所有数据库操作的 ORM。数据将存储在 PostgresSQL 服务器中。存储在数据库中的完整表是使用以下查询创建的:

CREATE TABLE airports
(
    id          SERIAL PRIMARY KEY,
    icao_code   VARCHAR(4) NOT NULL UNIQUE, -- the official ICAO code of the airport
    last_update TIMESTAMP  NOT NULL,        -- when were the information updated the last time?
    country     VARCHAR(2) NOT NULL,        -- two letter country code
    longitude   REAL       NOT NULL,        -- with 6 decimal places
    latitude    REAL       NOT NULL,        -- with 6 decimal places
    name        VARCHAR    NOT NULL         -- just a human readable name of the airport
);

正在运行 diesel migrations run生成 airports表定义和查询数据库工作没有任何问题。

现在我正在尝试查询所有机场的列表(它们的 ICAO 代码)以及相应的坐标以及到提供的坐标的距离。因此,我创建了以下 diesel-rs table!宏我自己

table! {
    airport_by_distance (icao_code) {
        icao_code -> Varchar,
        longitude -> Float8,
        latitude -> Float8,
        distance -> Float8,
    }
}

以及对应于diesel-rs的结构定义:

#[derive(QueryableByName)]
#[table_name = "airport_by_distance"]
struct AirportByDistance {
    icao_code: String,
    longitude: f64,
    latitude: f64,
    distance: f64,
}

根据我的理解,以下片段应该查询所需的信息:

use diesel::dsl::sql_query;

let latitude = 4.000001;
let longitude = 47.000001;

let query_sql = format!("SELECT icao_code, longitude, latitude, (3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance FROM airports ORDER BY distance;", lat=latitude, long=longitude);
let result = match sql_query(query_sql).load::<AirportByDistance>(database_connection) {
    Ok(result) => result,
    Err(error) => {
        error!("{:?}", error);
        return Err(());
    }
};

不幸的是,执行 load方法,结果为 DeserializationError(Custom { kind: UnexpectedEof, error: "failed to fill whole buffer" })错误。

执行的查询是:

SELECT icao_code,
       longitude,
       latitude,
       (3959.0 * acos(cos(radians(4.000001)) * cos(radians(latitude)) * cos(radians(longitude) - radians(47.000001)) +
                      sin(radians(4.000001)) * sin(radians(latitude)))) AS distance
FROM airports
ORDER BY distance;

我接过它并手动执行了它,但它运行得非常完美。我什至尝试删除计算并只选择列的子集,但也没有运气。

现在我不确定我做错了什么。我该如何解决这个问题?


使用固定代码编辑:对于那些对使用 Rasmus 的有用建议后如何编码感兴趣的人:

table!宏完全消失了,数据定义结构如下所示:

#[derive(Queryable)]
struct AirportByDistance {
    icao_code: String,
    longitude: f32,
    latitude: f32,
    distance: f64,
}

查询数据库的代码如下:

let result = match airports.select(
    (
        icao_code,
        longitude,
        latitude,
        sql::<Double>(
            &format!("(3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance", lat=latitude_reference, long=longitude_reference)
        )
    )
).load::<AirportByDistance>(database_connection)
{
    Ok(result) => result,
    Err(error) => {
        error!("{:?}", error);
        return Err(());
    }
};

for airport in result {
    info!(
        "AIRPORT: {} has {}nm distance",
        airport.icao_code, airport.distance
    );
}

最佳答案

我认为问题是反序列化器不知道查询列的原始类型。

尽量使用类型化的 diesel 名称/值,并仅在需要时使用显式 sql 字符串。而且我认为“假”表声明 airports_by_distance 没有帮助。也许是这样的:

use diesel::sql_types::Double;

let result = a::airports
    .select((
        a::icao_code,
        a::longitude,
        a::latitude,
        sql::<Double>(&format!("(3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance", lat=latitude, long=longitue)
    ))
    .load::<AirportByDistance>(&db)?

(手动使用 table! 宏基本上只是在运行程序时告诉 diesel 这样的表将存在于实际数据库中。如果不是这样,您将得到运行时错误。)

关于postgresql - 如何使用 diesel-rs 选择部分色谱柱?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66048172/

相关文章:

rust - Diesel "get_results"给出特征绑定(bind)错误

postgresql - Postgresql 中的数组是否存在反向重叠 (&&)?

php - 从 pgAdmin 进行查询。无法在 PHP 中正常运行

sql - 带有 DNS 记录的 Postgresql 数据库 : how to mass-increase serial

rust - 未能在阶乘函数中解析为 Rust 中的特征

rust - 可以在没有#[derive(Serialize)] 的情况下在枚举上实现/派生 Serialize 吗?

sql - Postgresql:查找继承表中的特定记录属于哪个表

multithreading - 为什么我的 Rust 线​​程没有并行运行?

rust - 关键字 "Some"和 "Simple"在 Rust 中有什么作用?

rust - 柴油。火箭和火箭.rs : don't understand why it wants a databases table