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

Filtering & Sorting

Filtering คือการจำกัด collection ให้เหลือเฉพาะแถวที่ client สนใจ ส่วน sorting เป็นตัวกำหนดลำดับ ทั้งสองอย่างเป็น query parameter บน collection และแค่มีธรรมเนียมเล็ก ๆ น้อย ๆ ก็ช่วยให้อ่านง่ายขึ้นมาก

รูปแบบที่ง่ายและเดาออกที่สุดคือหนึ่ง query parameter ต่อหนึ่ง field:

GET /articles?status=published&author=42

สำหรับช่วง (range) และ operator ธรรมเนียมที่นิยมคือใช้ operator แบบใส่วงเล็บหรือต่อท้าย:

GET /articles?createdAt[gte]=2026-01-01&views[gt]=1000

ให้ vocabulary ของ operator มีน้อยตัวและมีเอกสารกำกับ (gte, lte, gt, lt, ne, in) ไม่ว่าจะเลือกชุดไหน ก็ต้องใช้เหมือนกันหมดทุก collection

รับ parameter sort ที่ระบุรายการ field โดยใส่ - นำหน้าเพื่อเรียงจากมากไปน้อย:

GET /articles?sort=-createdAt,title

นั่นอ่านได้ว่า “ใหม่สุดก่อน แล้วค่อยเรียงตาม title จากน้อยไปมาก” ให้กำหนดไว้เลยว่า field ไหนบ้างที่ sort ได้ (การ sort บนคอลัมน์ที่ไม่มี index มีต้นทุนสูง) แล้วปฏิเสธที่เหลือด้วย 400

JavaScript
ข้อดี (Filtering & Sorting)ข้อแลกเปลี่ยน
client ดึงเฉพาะที่ต้องการ — ลด payloadquery parameter มากทำ URL ยาวและอ่านยาก
server-side filter ดีกว่า client-side filter ข้อมูลทั้งหมดfilter ที่ซับซ้อนต้องการ query language (OData, custom)
sort ฝั่ง server ใช้ database index — เร็วกว่า sort ใน memoryต้อง validate filter/sort parameter ป้องกัน SQL injection
filter + sort รวมกันใน request เดียวmulti-field sort ทำ URL ซับซ้อน

ไม่ Validate Filter Parameter อาการ:

  • GET /users?sort=; DROP TABLE users--
  • inject SQL ผ่าน sort parameter
  • whitelist field ที่ filter/sort ได้: if (!['name','email','createdAt'].includes(sort)) throw

Filter ที่ Expensive โดยไม่มี Index อาการ:

  • GET /orders?status=pending — query WHERE status = 'pending' บน table ล้าน record
  • ไม่มี index บน status column — full table scan ทุก request
  • สร้าง index บน field ที่ filter บ่อย หรือจำกัด filter ที่รองรับ

💡 ตัวอย่างจากของจริง

GitHub API:

  • GET /repos/\{owner\}/\{repo\}/issues?state=open&labels=bug&sort=created&direction=desc
  • filter หลายมิติ, sort พร้อมกัน ใน request เดียว

Stripe API:

  • GET /charges?created[gte]=1609459200&created[lte]=1640995199&limit=100
  • range filter ด้วย bracket notation — filter วันที่ระหว่าง 2 ช่วง
`?sort=-createdAt,title` หมายความว่าอย่างไร?
ทำไมต้องทำ allowlist ของ field ที่ filter และ sort ได้?
parameter ของ filter และ sort ควรอยู่ที่ไหน?