dieselのメモ

2020-01-03

所用でdieselを使っているのですが、ドキュメントから探すのが難しかったり、実現できなかったりすることがパッと分からなかったりします。 ということで、本記事は触ってみて気づいたことを書き溜めておくチラ裏です。気が向いたときに追記してゆく予定です。

生SQLの実行

dieselではwindow関数やsubqueryをサポートしていません。 そのため、paginationはsqlを直にいじることで実現しています。

頻繁に使う記述はこのように作ると良いのですが、とりあえず動かしたい場合にはなかなか手間です。ということで、生SQLを扱う方法を覚えておくと便利です。

生SQLの実行にはsql_queryを使うと、load時にby-nameでマッピングを行ってくれます。 マッピングする先のstructでは、QueryableByNameをderiveしておきます。

#[derive(QueryableByName, Serialize, Debug)]
pub struct LastUpdate {
    #[sql_type = "Datetime"]
    pub dt: chrono::NaiveDateTime,
}

use diesel::sql_query;
use diesel::sql_types::Integer;

sql_query(
r#"
  SELECT x.*, updated_at as dt
  FROM hoge
  LIMIT ?
"#
)
.bind::<Integer, _>(5)
.load::<(Hoge, Rank)>(&*conn)
.expect("cannot execute ....")

association

関連するテーブルを引っ張ってくる場合は、structに derive(Associations)#[belongs_to(XXX)] を付けて belonging_to でIDを指定して取得できます。 これは WHERE IN による絞り込みが行われます。

SELECT * FROM hoge
WHERE IN (1,2,3....)

そのため、IDが該当SQLの実行時に決まっている必要があり、subqueryでは実行できません。 2度クエリを実行するため、パフォーマンスが気になる場合は生SQLなどで頑張りましょう。

grouped_by

SQLの group_by とは異なり、既にloadしたデータをグルーピングする関数が grouped_by です。 外部キーでくっつきます。 この後にzipすることで、親データと小データの配列をセットにした構造が得られます。 詳しくは↓で。

1件取得

普通に find が使えます。 derive(Identifiable) を付けたstructでloadすること。

GROUP BYした際のselect制限

QueryBuilderにはGROUP BYに現れたカラムのみSELECTで指定できるという、MySQL 8.0のエンジンより強い制約があります。 そのため、下記のような記述は生SQLで書く必要があります(AとBは1:多対応)。

SELECT A.*
FROM B
LEFT JOIN A on B.a_id = A.id
GROUP BY B.A_id

便利なURLたち

まとめ

diesel楽しい。 気づいたことがあれば追記してゆきます。

development

最近読んだ本のまとめ

お部屋updates - 2019.09

comments powered by Disqus