Filtering & Sorting
Filtering คือการจำกัด collection ให้เหลือเฉพาะแถวที่ client สนใจ ส่วน sorting เป็นตัวกำหนดลำดับ ทั้งสองอย่างเป็น query parameter บน collection และแค่มีธรรมเนียมเล็ก ๆ น้อย ๆ ก็ช่วยให้อ่านง่ายขึ้นมาก
Filtering
หัวข้อที่มีชื่อว่า “Filtering”รูปแบบที่ง่ายและเดาออกที่สุดคือหนึ่ง 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
Sorting
หัวข้อที่มีชื่อว่า “Sorting”รับ parameter sort ที่ระบุรายการ field โดยใส่ - นำหน้าเพื่อเรียงจากมากไปน้อย:
GET /articles?sort=-createdAt,titleนั่นอ่านได้ว่า “ใหม่สุดก่อน แล้วค่อยเรียงตาม title จากน้อยไปมาก” ให้กำหนดไว้เลยว่า field ไหนบ้างที่ sort ได้ (การ sort บนคอลัมน์ที่ไม่มี index มีต้นทุนสูง) แล้วปฏิเสธที่เหลือด้วย 400
การนำทั้งสองมาใช้ใน code
หัวข้อที่มีชื่อว่า “การนำทั้งสองมาใช้ใน code”| ข้อดี (Filtering & Sorting) | ข้อแลกเปลี่ยน |
|---|---|
| client ดึงเฉพาะที่ต้องการ — ลด payload | query 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— queryWHERE status = 'pending'บน table ล้าน record- ไม่มี index บน
statuscolumn — 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 ช่วง