☠️
SupabaseのJavaScript Client Libraryで多対多のリレーションを扱う(抽出/フィルタリング編)
はじめに
SupabaseのJavaScript Client Libraryを使って、多対多リレーションシップのデータを全件抽出したりフィルタリングする際に、知らないと躓きやすい作法をまとめました。
準備
検証用に、SupabaseのSQL Editorを使って三つのテーブルを用意します。
- 記事テーブル
create table public.articles (
id bigint generated by default as identity primary key,
title text not null,
slug text not null unique,
content text not null
);
- タグテーブル
create table public.tags (
id bigint generated by default as identity primary key,
name text not null unique
);
- 中間テーブル
create table public.articles_tags (
article_id bigint not null references public.articles on delete cascade,
tag_id bigint not null references public.tags on delete cascade,
primary key (article_id, tag_id)
);
記事データを全件抽出する
const { data: articles, error } = await supabase
.from('articles')
.select('title,slug,tags(name)');
// 全フィールドを指定する場合は
// .select('*,tags(name)');
特定のタグでフィルタリングして記事データを抽出する
以下の既述で抽出できそうですが、少し問題があります。
複数のタグと関連付けされている記事データが抽出された場合に、抽出条件のタグしか参照できなくなってしまいます。
例えば、「政治」「スポーツ」「エンタメ」のタグと関連付けされている記事データAがあったとします。
記事全件を「スポーツ」タグでフィルタリングした際に、抽出された記事データAのタグ情報が「スポーツ」だけになってしまうということです。
const tagName = 'abc';
const { data: articles, error } = await supabase
.from('articles')
.select('title,slug,tags(name)')
.eq('tags.name', tagName);
これはSQLで処理した際と同じ挙動なので、以下のように対処できます。
const tagName = 'abc';
const { data: tag, error } = await supabase
.from('tags')
.select('articles(title,slug,tags(name))')
.eq('name', tagName)
.single();
const articles = tag.articles;
Discussion