我如何 select 使用 diesel-rs 的列子集?
How do I select a subset of columns with diesel-rs?
我现在正在努力几个小时来查询 table 的可用列的子集,并在其中包含一个计算。我知道这不是在 select 查询中执行计算的最佳方式,但目前,我只是在研究原型,它应该是可行的。
我在后端实现中使用 diesel-rs
作为我所有数据库操作的 ORM。数据将存储在 PostgresSQL 服务器中。完整的 table - 存储在数据库中 - 是使用以下查询创建的:
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
table 定义并且查询数据库没有任何问题。
现在我正在尝试查询所有机场(它们的 ICAO 代码)的列表以及相应的坐标以及到提供的坐标的距离。因此,我自己创建了下面的 diesel-rs
table!
宏
table! {
airport_by_distance (icao_code) {
icao_code -> Varchar,
longitude -> Float8,
latitude -> Float8,
distance -> Float8,
}
}
以及diesel-rs
定义对应的struct:
#[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;
我接过它并手动执行了它,但它完美无缺。我什至尝试删除计算并只 selecting 列的子集,但也没有运气。
现在我不确定我做错了什么。我该如何解决这个问题?
使用固定代码进行编辑:对于那些对使用 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
);
}
我认为问题在于反序列化器不知道查询列的原始类型。
尽量使用类型化的柴油机 names/values,仅在需要时才使用明确的 sql 字符串。而且我认为“假”table 声明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!
宏基本上只是告诉柴油机 运行 程序时实际数据库中会存在这样的 table 。如果那不是真的,你会出现运行时错误。)
我现在正在努力几个小时来查询 table 的可用列的子集,并在其中包含一个计算。我知道这不是在 select 查询中执行计算的最佳方式,但目前,我只是在研究原型,它应该是可行的。
我在后端实现中使用 diesel-rs
作为我所有数据库操作的 ORM。数据将存储在 PostgresSQL 服务器中。完整的 table - 存储在数据库中 - 是使用以下查询创建的:
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
table 定义并且查询数据库没有任何问题。
现在我正在尝试查询所有机场(它们的 ICAO 代码)的列表以及相应的坐标以及到提供的坐标的距离。因此,我自己创建了下面的 diesel-rs
table!
宏
table! {
airport_by_distance (icao_code) {
icao_code -> Varchar,
longitude -> Float8,
latitude -> Float8,
distance -> Float8,
}
}
以及diesel-rs
定义对应的struct:
#[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;
我接过它并手动执行了它,但它完美无缺。我什至尝试删除计算并只 selecting 列的子集,但也没有运气。
现在我不确定我做错了什么。我该如何解决这个问题?
使用固定代码进行编辑:对于那些对使用 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
);
}
我认为问题在于反序列化器不知道查询列的原始类型。
尽量使用类型化的柴油机 names/values,仅在需要时才使用明确的 sql 字符串。而且我认为“假”table 声明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!
宏基本上只是告诉柴油机 运行 程序时实际数据库中会存在这样的 table 。如果那不是真的,你会出现运行时错误。)