概要
データベースに対してクエリを発行する際は、QueryBuilderオブジェクトを使用します。
Modelのqueryメソッド(staticメソッド)を実行すると、QueryBuilderを取得できます。
メソッドチェーンによってクエリを構築していき、thenメソッドを実行すると、構築したクエリが実行されます。
const queryBuilder = Project.query();
queryBuilder.then(projects => console.log(projects));
// awaitでも実行可能
const projects = await queryBuilder.where('name', '=', 'hogepiyo');
Modelの定義についてはこちらを参照。
Fetch Queries
テーブルの全レコードを取得する
const projects = await Project.query();
// select "projects".* from "projects"
console.log(projects.every(project => project instanceof Project)); // true
指定したIDを保持するレコードを取得する
whereメソッドを使用して、返却されるレコードを制限できます。
const project = await Project.query().where({ id: 1 }).first();
// select "projects".* from "projects" where "id" = 1
console.log(project instanceof Project); // true
// 上記と同様のSQLを実行する
await Project.query().where('id', '=', 1).first();
await Project.query().where('id', 1).first()
// findByIdメソッドを使用することで、より簡潔に記述できる
await Project.query().findById(1);
複雑なクエリ
const tasks = await Task
.query()
.select('name', 'description')
.where('deadline', '>=', new Date())
.orWhere(function() {
this
.where('assignedTo', '=', 1)
.andWhere('projectId', '=', 2);
})
.orderBy('deadline', 'asc');
// select "name", "description" from "tasks" where "deadline" >= '2018-08-19 01:43:33.853' or ("assignedTo" = 1 and "projectId" = 2) order by "deadline" asc
Insert Queries
レコードを作成する
const user = await User.query().insert({ name: 'fuga', email: 'fuga@example.com' });
// insert into "users" ("email", "name") values ('fuga@example.com', 'fuga') returning "id"
console.log(user); // User { name: 'fuga', email: 'fuga@example.com', id: 3 }
const users = await User.query().insert([
{ name: 'hoge', email: 'hoge@example.com' },
{ name: 'piyo', email: 'piyo@example.com' }
]);
// insert into "users" ("email", "name") values ('hoge@example.com', 'hoge'), ('piyo@example.com', 'piyo') returning "id"
console.log(users);
// [ User { name: 'hoge', email: 'hoge@example.com', id: 5 },
// User { name: 'piyo', email: 'piyo@example.com', id: 6 } ]
作成されたレコードの全カラムを取得する
insertメソッドを実行すると、引数で指定したプロパティとプライマリキーのみが設定された状態でModelのインスタンスが返却されます。
カラムにデフォルト値を設定しているなどの都合で、すべてのカラムが必要な場合は、insertAndFetchメソッドを使用します。
const task = await Task.query().insert({ assignedTo: 1, projectId: 1, name: 'sample' });
console.log(task); // Task { assignedTo: 1, projectId: 1, name: 'sample', id: 1 }
const taskWithAllProps = await Task.query().insertAndFetch({ assignedTo: 1, projectId: 1, name: 'sample' });
// PostgreSQLであれば、
// `await Task.query().insert({ assignedTo: 1, projectId: 1, name: 'sample' }).returning('*')`
// でも可
console.log(taskWithAllProps);
// Task {
// assignedTo: 1,
// projectId: 1,
// name: 'sample',
// id: 2,
// description: null,
// deadline: null,
// createdAt: 2018-08-18T17:18:12.358Z,
// updatedAt: 2018-08-18T17:18:12.358Z }
Update Queries
特定のレコードを更新する
patchまたはupdateメソッドを使用することで、レコードの更新を行うことができます。
戻り値は、更新されたレコードの行数です。
patchとupdateは、ModelのjsonSchemaプロパティでrequiredと指定されたプロパティの扱いが異なります。
updateメソッドは、required指定されたプロパティが引数に指定されなかった場合、ValidationErrorを発生させます。
そのため、レコードの一部のカラムのみを更新する際はpatch、全カラムを更新する際はupdateを使うと良いと思います。
const num = await User.query().where({ id: 1 }).patch({ name: 'hoge' });
// update "users" set "name" = 'hoge' where "id" = '1'
console.log(num); // 1
// ModelのjsonSchemaプロパティでrequiredと指定したプロパティを省略すると、
// ValidationErrorが発生する
await User.query().where({ id: 1 }).update({ name: 'hoge' }));
// ValidationError: email: is a required property
更新後、最新レコードを取得する
patchAndFetchByIdまたはupdateAndFetchByIdメソッドを使用すると、
更新されたレコードの件数ではなく、更新後のレコードそのものを取得することができます。
const user = await User.query().patchAndFetchById(1, { name: 'piyo' });
// update "users" set "name" = 'piyo' where "users"."id" = '1'
console.log(user); // User { name: 'piyo', id: 1, email: 'taro@example.com' }
// PostgreSQLの場合は、`await User.query().patch({ name: 'piyo' }).where({ id: 1 }).returning('*')`でも可
Delete Queries
特定のレコードを削除する
deleteメソッドを使用します。
戻り値は、削除されたレコードの行数です。
const num = await User.query().delete().where({ id: 3 });
// delete from "users" where "id" = '3'
console.log(num); // 1
参考