1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Supabase】1対1のテーブルのリレーション先のデータをオブジェクト形式で取得する方法

Last updated at Posted at 2025-02-08

はじめに

お疲れ様です、りつです。

タイトルの通りなのですが、1対1のリレーションが貼られているテーブルに対して、リレーション先のデータ形式を配列ではなくオブジェクトで取得する方法をまとめました。

文章だとわかりにくいかと思いますので例を示すと、以下のようなイメージです。

  • Before
    {
        "user_id": "ritsu",
        "profiles": [ // ここが配列形式の中にオブジェクトとして返却されている
            {
                "user_name": "りつ",
                "avatar_url": null
            }
        ]
    }
    
  • After
    {
        "user_id": "ritsu",
        "profiles": { // オブジェクト形式で返却されている
            "user_name": "りつ",
            "avatar_url": null
        }
    }
    

なお、1対多、多対多のテーブル構造の場合の設定については以下の公式ドキュメントに記載があります。

問題

以下の1対1の関係のテーブルが存在している状況で、ユーザー情報(ユーザーID、ユーザー名、アバターのU)の取得を行いたいと考えていました。

accounts

ユーザーアカウント

No PK FK カラム名 NotNull デフォルト
1 user_id varchar
2 password varchar

profiles

ユーザープロフィール

No PK FK カラム名 NotNull デフォルト
1 profile_id uuid
2 user_id varchar
3 user_name varchar
4 avatar_url varchar
5 introduction text

accounts.user_idprofiles.user_idは外部キーでリレーションを設定しているのですが、以下のソースコードを使用してデータ取得を行ったところ、レスポンスのdataprofilesが配列になっていました。

src/utils/supabaseFunctions.ts
import { User } from '@/domains/user';
import { supabase } from './supabase';

export const fetchUser = async (id: string): Promise<User> => {
  const { data, error } = await supabase.from('accounts').select('user_id, profiles(user_name)').eq('user_id', id).single();

  if (error) {
    throw new Error(error.message);
  }

  return data;
};
レスポンスデータ(dataの中身)
{
    "user_id": "ritsu",
    "profiles": [
        {
            "user_name": "りつ",
            "avatar_url": null
        }
    ]
}

1対1の関係なので、profilesの中身は配列ではなく、オブジェクトで取得できればと思い、設定方法を調べました。

解決方法

結論、profiles.user_idに対して、ユニークキー制約を設定してあげる必要がありました。

Supabaseの管理画面から設定する方法は以下の通りです。

  1. テーブルエディターを開く
  2. 対象テーブル名の横にある・・・ > Edit tableを選択
    スクリーンショット 2025-02-08 135236.png
  3. Columnsセクションの対象カラムの右側にある歯車マーク > Is Uniqueにチェックを入れて保存
    スクリーンショット 2025-02-08 135116.png

上記設定後、以下のようにデータが返却されるようになりました。

レスポンスデータ(dataの中身)
{
    "user_id": "ritsu",
    "profiles": {
        "user_name": "りつ",
        "avatar_url": null
    }
}

おわりに

まとめ
1対1のリレーションテーブルからデータ取得を行う際は、リレーション先テーブルの外部キーにユニークキー制約の設定が行うと、レスポンスデータがシンプルになる

今回のケースの場合、必要な情報(user_iduser_nameavatar_url)は全てprofilesテーブルから取得可能なため、リレーションで取得する必要性は低いかもしれません。

ただ、今後両テーブルそれぞれからデータの取得が必要になったパターンを見越して1対1のリレーション取得方法を調べてみました。

どなたかのご参考になれば幸いです。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?