質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

1082閲覧

RustのORMであるDieselを使ってデータの取得・削除を一括で行いたい

ts21

総合スコア32

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2022/12/31 06:11

前提

dieselを使って以下のHumansテーブルに対し、一括でfetch, deleteを行いたいです。(PostgresSQL v.14)

up.sql

1CREATE TABLE Humans ( 2 name VARCHAR(20) PRIMARY KEY, 3 information JSON NOT NULL 4); 5

model.rs

1#[derive(Insertable, Queryable, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 2#[table_name = "humans"] 3pub struct Humans { 4 pub name: String, 5 pub information: serde_json::Value, 6}

現在はいずれも以下のようにイテレータやfor文を使って実装しています。

mod.rs

1pub fn fetch_humans(conn: &PgConnection, targets: &[String]) -> Vec<Option<Vec<Nodes>>> { 2 targets.iter() 3 .map(|target| { 4 schema::humans::dsl::humans 5 .filter(schema::humans::name.eq(target)) 6 .load::<Humans>(conn) 7 .optional() 8 .expect("Error fetching humans") 9 }) 10 .collect::<Vec<_>>() 11} 12 13pub fn delete_humans(conn: &PgConnection, targets: &[String]) { 14 for target in targets { 15 diesel::delete(schema::humans::dsl::humans) 16 .filter(schema::humans::name.eq(target)) 17 .execute(conn) 18 .expect("Error deleting humans"); 19 } 20}

やりたいこと

この実装でも問題ないのですが、クエリ回数を減らし、より効率的に処理したいと思っています。

diesel::insert_intoのように実現できれば嬉しいのですが、fetchやdeleteに関してはそのようなメソッドが用意されていません。(私が調べた限り)

考えたこと

diesel::sql_queryの中でWITH句を使った生のSQLを書けばできるかなと思ったのですが、targetsの中身を取り出してsql_queryの中に書き込む方法が分からず停滞しています。

もし、diesel固有の解決策やsql_queryでの解決策に知見がある方がいらっしゃれば、ご意見いただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

eqの代わりにeq_anyを使えば一つのSELECTまたはDELETE文で複数の値を指定できます。SQLのWHERE 〜 IN ()に対応しています。(ドキュメント

rust

1// 注:戻り値型を変更しました 2pub fn fetch_humans(conn: &mut PgConnection, targets: &[String]) -> Vec<Humans> { 3 schema::humans::dsl::humans 4 .filter(schema::humans::name.eq_any(targets)) 5 .load::<Humans>(conn) 6 .expect("Error fetching humans") 7} 8 9pub fn delete_humans(conn: &mut PgConnection, targets: &[String]) { 10 diesel::delete(schema::humans::dsl::humans) 11 .filter(schema::humans::name.eq_any(targets)) 12 .execute(conn) 13 .expect("Error deleting humans"); 14}

なお、Dieselは、PostgreSQLではIN ()の代わりに= ANY()を使うそうです。

On PostgreSQL, this method automatically performs a = ANY() query.

以下のようにしてSQLをデバッグ表示したところ、たしかに= ANY()が使われていました。

rust

1pub fn fetch_humans(conn: &mut PgConnection, targets: &[String]) -> Vec<Humans> { 2 use diesel::pg::Pg; 3 4 let query = schema::humans::dsl::humans 5 .filter(schema::humans::name.eq_any(targets)); 6 let sql = diesel::debug_query::<Pg, _>(&query); 7 println!("{}", sql);

sql

1SELECT "humans"."name", "humans"."information" FROM "humans" WHERE ("humans"."name" = ANY($1)) -- binds: [["alice", "cindy", "david"]]

投稿2022/12/31 09:39

tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ts21

2022/12/31 10:29

ありがとうございます!eq_anyは見逃していました... 機能を損なわずにスマートなクエリとすることができました!
ts21

2022/12/31 10:30

ちなみに戻り値をそのままにするなら .optional().iter().collect::<Vec<_>>()とすれば近づけそうです。 (参照&Optionとなってしまうので、何かしらの対策が必要)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問