[Supabase] JavaScirptのデータベース検索まとめ

2023年2月7日火曜日

Supabase

t f B! P L

enter image description here

Supabaseはいわゆる BaaS (Backend As A Service)で、ちまたでは Firebase の RDB(PostgreSQL)版といわれいる。 公式やサードパーティの JavaScirptライブラリを使ってクライアントサイドからSQLが実行できる。

この記事では、JavaScirptから発行するSQLの基本的な使用方法を紹介する。

スポンサーリンク

全レコード取得

tasks テーブルの全レコード+全カラムを取得し、id 列でソートする場合。

const { data, error } = await supabase
  .from('tasks')
  .select('*');

ソート順を指定

ソート順の指定は order 関数を使用する。

// priority列の昇順でソート
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .order('priority');

複数のカラムをソート順に指定

複数キーでソートする場合は、order 関数を複数連ねる。

// complete と priority の昇順でソート
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .order("complete")
  .order("priority");

降順ソート

降順でソートする場合は、order の第二引数にオプションを指定する。

// priority列の降順でソート
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .order("priority", { ascending: false });

取得するカラムを指定

取得するカラムを絞る場合は、select の引数にカラム名をカンマ区切りで指定する。

const { data, error } = await supabase
  .from('tasks')
  .select('id, name, complete, priority');

抽出条件を指定

等価(=)

等価(A = B)は eq 関数を使用する。

const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .eq("complete", true); // complete = true

不等価(!=)

不等価(A != B)は eq 関数を使用する。

const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .neq("complete", true); // complete != true

以上(>=)、より大きい(>)

以上は gte、より大きいは gt を使用する。

//以上
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .gte("priority", 2); // priority >= 2

//より大きい
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .gt("priority", 2); // priority > 2

以下(<=)、未満(<)

以下は lte、未満は lt を使用する。

//以下
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .lte("priority", 2); // priority <= 2

//未満
const { data, error } = await supabase
  .from('tasks')
  .select('*')
  .lt("priority", 2); // priority < 2

IN句

複数の候補を条件に指定する IN句は、in 関数で指定する。

// SELECT * FROM tasks WHERE priority IN( 1, 3, 5)
const { data, error } = await supabase
  .from('tasks')
  .select("*")
  .in("priority", [1, 3, 5])

スポンサーリンク

テーブル結合

Supabaseのデータベースは RDB(PostgreSQL)なので、もちろんテーブル結合もできる。

さらに、テーブルに外部キーを設定しておくことで、SQLに結合条件を書かなくても自動的に外部キーで結合した結果でデータが取得できる。

テーブル結合の例

商品テーブル(products)と、売上テーブル(sales)があり、売上テーブルの product_id に商品テーブルへの外部キーを設定する例でサンプルコードを紹介する。

ER図

上の2つのテーブルを結合(JOIN)して結果を取得するサンプルコードは次のとおり。

const { data, error } = await supabase
.from('products')
.select(`
  name,
  unit_price,
  sales (
    num
  )
`)

上のコードを実行すると、次のような結果が得られる。

注目すべきポイントとして、一般的なSQLの場合、SELECT 文の結果は2次元の表形式でとなるが、JavaScirptで発行するクエリでは、form で指定した軸テーブルの結果に結合先テーブルの結果が配列で含まれる形となる。

[
  {
    "name": "メロン",
    "unit_price": 500,
    "sales": [
      {
        "num": 2
      },
      {
        "num": 3
      }
    ]
  },
  {
    "name": "バナナ",
    "unit_price": 100,
    "sales": [
      {
        "num": 3
      }
    ]
  }
]

デフォルトは外部結合

さらに特筆すべき点として、テーブル結合はデフォルト外部結合となることである。そのため、上のクエリで結合先のレコードが存在しないは、次の例のとおり結合先のテーブル(sales)の配列が空の結果が返ってくる。

[
  {
    "id": 1,
    "name": "メロン",
    "unit_price": 500,
    "sales": []
  }
]

内部結合でJOINする

結合先のテーブル名の後ろに !inner を付けることで、内部結合でJOINできる。

const { data, error } = await supabase
.from('products')
.select(`
  name,
  unit_price,
  sales!inner (
    num
  )
`)

結合先のテーブルで絞り込み

結合先のテーブルに対する絞り込み条件は、<テーブル名>.<カラム名> で項目を指定する。

const { data, error } = await supabase
.from('products')
.select(`
  name,
  unit_price,
  sales (
    num
  )
`)
.gte("sales.num", 3)

リアルタイムにデータの変更を検知する

リアルタイムにデータの変更を、他のクライアントに通知できる。
詳細は、こちらの記事を参照。
Supabaseでデータベースの変更をリアルタイムに検知する

スポンサーリンク

まとめ

JavaScirptから Supabaseのデータベースする場合は、純粋なSQLではなく、ここまで紹介したような JavaScirpt APIを用いる必要があるため最初は戸惑うかもしれない。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ