7ก.ค.
จัดอันดับข้อมูลด้วย Tag ใน JSONB บน PostgreSQL
postgresqlsqldatabase
10 ก.ค. 68 , 14:03
ใช้ฟังก์ชัน jsonb_array_elements_text เพื่อแตกรายการแท็กใน jsonb ออกมาเป็นแถว จากนั้นนับจำนวนแถวที่ตรงกับเงื่อนไข แล้วจัดกลุ่มและเรียงลำดับผลลัพธ์ เพื่อหาข้อมูลที่มีแท็กตรงกันมากที่สุด

ในการพัฒนาระบบที่ต้องจัดการกับ tags ซึ่งจัดเก็บในคอลัมน์ประเภท jsonb ของ PostgreSQL เรามักเจอกับโจทย์ที่ต้องค้นหาและจัดอันดับข้อมูลตามจำนวนแท็กที่ตรงกับเงื่อนไขมากที่สุด

หัวใจสำคัญของการทำ Query ลักษณะนี้คือการใช้ LATERAL JOIN ร่วมกับฟังก์ชัน jsonb_array_elements_text() เพื่อแตกอาร์เรย์ใน jsonb ออกมาเป็นแถว (Unnest) สำหรับนำไปเปรียบเทียบและนับจำนวน



Query หลัก: ค้นหาและจัดอันดับ

Query ต่อไปนี้ใช้สำหรับค้นหาเอกสารที่มีแท็กตรงกับ ARRAY[...] ที่กำหนดไว้อย่างน้อย 1 แท็ก และเรียงลำดับตามจำนวนที่ตรงกันมากที่สุด

หลักการทำงาน:

1.LATERAL jsonb_array_elements_text(d.tag_data): แตกสมาชิกทั้งหมดใน tag_data ของแต่ละแถวออกมาเป็น text
2.WHERE tags.tag = ANY(ARRAY[...]): กรองเอาเฉพาะแถว (แท็ก) ที่ตรงกับค่าในอาร์เรย์ที่ต้องการ
3.GROUP BY d.id: จัดกลุ่มผลลัพธ์ตามเอกสารเดิม
4.COUNT(tags.tag): นับจำนวนแท็กที่ผ่านการกรองมาได้ในแต่ละกลุ่ม
5.ORDER BY matching_tags DESC: จัดเรียงผลลัพธ์ตามจำนวนที่นับได้จากมากไปน้อย





กรณีเพิ่มเติม: แสดงผลลัพธ์ทั้งหมด (รวมที่ไม่ตรงเลย)

หากต้องการให้ผลลัพธ์แสดงเอกสารทั้งหมดรวมถึงเอกสารที่ไม่มีแท็กตรงกันเลย (มีค่า matching_tags เป็น 0) ให้ปรับไปใช้ LEFT JOIN และย้ายเงื่อนไขไปไว้ใน ON clause