ข้ามไปยังเนื้อหา

Querying with the Client SDK

query builder ของ supabase-js เป็น TypeScript wrapper แบบ fluent ที่สร้าง PostgREST request เดียวกับที่คุณเขียนเองได้ และทุก call จะ resolve ออกมาเป็น object { data, error } แทนที่จะ throw

ทุกอย่างที่เห็นเป็น raw query string ในบทก่อนหน้ามี method ที่ตรงกันบน query builder เลือก table ด้วย .from() เลือก column ด้วย .select() filter ด้วย .eq() (และตัวพี่น้องของตัวเอง) แล้วเรียงลำดับด้วย .order()

const { data, error } = await supabase
.from('movies')
.select('id, title, year')
.eq('year', 2020)
.order('year', { ascending: false });

การเขียนข้อมูลก็ทำงานแบบเดียวกัน .insert(), .update() และ .delete() map ไปหา HTTP verb ที่ PostgREST expose ไว้ตรง ๆ

await supabase.from('movies').insert({ title: 'Arrival', year: 2016, director_id: 3 });
await supabase.from('movies').update({ year: 2021 }).eq('id', 1);
await supabase.from('movies').delete().eq('id', 1);

query ของ supabase-js ไม่เคย throw เมื่อ request ล้มเหลว — จะ resolve เป็น object รูปแบบ { data, error } เสมอ ถ้า request สำเร็จ error จะเป็น null และ data จะมี row อยู่ข้างใน ถ้าล้มเหลว data จะเป็น null และ error จะถูกเติมค่ามาแทน เพราะไม่มี exception ให้ catch คุณต้องเช็ค error เองทุกครั้ง ไม่งั้น request ที่ล้มเหลวจะดูเหมือนผลลัพธ์ว่างเปล่าไปเฉย ๆ

error เป็น PostgrestError ที่มี 4 field ที่ควรรู้จัก

  • message — คำอธิบายที่มนุษย์อ่านเข้าใจว่าเกิดอะไรผิดพลาด
  • code — อาจเป็น Postgres error code (เช่น unique-constraint violation) หรือ code เฉพาะของ PostgREST
  • details — context เพิ่มเติมจาก Postgres ถ้ามี
  • hint — คำแนะนำสำหรับแก้ปัญหา ถ้า Postgres หรือ PostgREST ให้มาได้
const { data, error } = await supabase.from('movies').select('id, title').eq('year', 2020);
if (error) {
console.error(`query failed [${error.code}]: ${error.message}`);
} else {
console.log(data);
}

เหมือนกับ raw REST API query builder embed related table ได้โดยระบุชื่อ table นั้นไว้ข้างใน select() — PostgREST ยังคงทำงานเบื้องหลังด้วยการตาม foreign key เหมือนเดิม builder แค่ให้วิธีเรียกที่ typed และ chain ได้

const { data, error } = await supabase.from('movies').select('title, directors(name)');
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!);
async function recentMovies() {
const { data, error } = await supabase
.from('movies')
.select('id, title, year, directors(name)')
.eq('year', 2020)
.order('title', { ascending: true });
if (error) {
console.error('failed to load movies:', error.message);
return [];
}
return data;
}
flowchart LR
  from[".from('movies')"] --> select[".select('id, title, year')"]
  select --> eq[".eq('year', 2020)"]
  eq --> order[".order('year')"]
  order --> http["One HTTP request to PostgREST"]
  http --> result["Result: data and error"]
สร้าง PostgREST request เดียวจากการ chain method
ผลลัพธ์จาก query ของ supabase-js มีรูปแบบอะไรเสมอ
ทำไมต้องเช็ค field error เอง แทนที่จะพึ่ง try/catch
การรวม method ไหนที่ filter movie ให้เหลือปี 2020 แล้วเรียงตาม year จากมากไปน้อย
query builder embed table directors ที่เกี่ยวข้องเข้าไปใน query ของ movies ได้อย่างไร