จัดการ Database Model บน Go ง่ายๆ ด้วย Ent Framework !!!
สวัสดีครับ วันนี้ผมจะมาสอนวิธีการจัดการ Database model ของ Go ด้วย Ent Framework กันครับ โดยเรามาเริ่มจากทำความรู้จัก Ent กันก่อนดีกว่า
Ent เป็น Framework ของ Golang ที่ช่วยในการสร้างและจัดการ application ที่มี Data Model ขนาดใหญ่ โดยจุดเด่นของ Ent ก็คือ
- สามารถสร้าง schema ได้ด้วยภาษา Go
- schema ที่ถูกสร้างขึ้น จะอยู่ในรูปแบบของ Graph Structure
- เขียน Query ง่าย เพราะมี function รองรับสำหรับ CRUD
- เพราะ Schema ถูกเก็บอยู่ในรูปแบบของ Code ภาษา Go จึงง่ายต่อการแก้ไข
หลังจากเราได้รู้จัก Ent กันไปแล้ว ต่อไปจะเป็นเนื้อหาในครั้งนี้กันครับ โดยในครั้งนี้เรื่องที่ผมจะสอน ประกอบไปด้วย
- การ Create Schema
- Field
- Edge (Relation)
- CRUD API
ทั้งหมด 4 หัวข้อด้วยกัน ถ้าพร้อมแล้ว เรามาเริ่มกันเลยครับ
Prerequisite
- พื้นฐาน ภาษา Go
- Database (ในครั้งนี้ผมจะใช้เป็น postgresql นะครับ)
Installation
เริ่มจากทำการ setup go module ของ project ดังนี้
go mod init <project>
ตามด้วยติดตั้ง Ent
go get -d entgo.io/ent/cmd/ent
Create Schema
หลังจากติดตั้งเสร็จแล้ว เรามาเริ่มสร้าง Schema กัน ด้วยคำสั่ง
go run entgo.io/ent/cmd/ent init <schema name>
โดยในตัวอย่างจะลองสร้าง Schema User ดูนะครับ
go run entgo.io/ent/cmd/ent init User
Command นี้จะทำการสร้าง schema User ที่ directory <project>/ent/schema/
ดังรูป
โดยหน้าตาข้างในไฟล์จะเป็นไปตาม code ด้านล่างนี้
ก่อนที่จะพูดเรื่อง Field เรามาลองเพิ่ม Field ดูใน Schema นี้ก่อน โดยในตัวอย่างข้างล่างผมจะลองเพิ่ม Field ชื่อ name และ age ดู
หลังจากลองเพิ่ม Field ดูแล้ว ต่อไปก็พิมพ์คำสั่งตามด้านล่าง
go generate ./ent
เมื่อพิมพ์คำสั่งนี้ ent จะทำการ generate ไฟล์ที่เก็บฟังก์ชันสำหรับ CRUD ของ Schema นั้นไว้ ดังรูปด้านล่าง
จากนั้นเรามาลองสร้าง Ent Client สำหรับจัดการกับ Schema ตามตัวอย่างด้านล่างนี้
หลังจากสร้าง Client แล้วเรามาลองสร้าง Entity ให้ Schema User กัน
ด้านบนจะเป็นตัวอย่างการเพิ่ม Entity ของ Schema User โดยการกำหนด ชื่อของ User เป็น “Somsak” และ อายุเป็น “30”
จากนั้นก็ลอง Query ดูด้วย Method Query และใช้ Where ในการกำหนดเงื่อนไขว่า ชื่อของ User ต้องชื่อ “Somsak”
โดยรูปด้านล่างนี้คือผลลัพธ์ที่ได้
หลังจากดูตัวอย่างไปแล้ว ต่อไปเรามาดูรายละเอียดกันดีกว่า
Field
Field ใน Schema เปรียบเสมือน Column ในDatabaseโดยเราสามารถเพิ่ม Field ใน Schema ได้ผ่านทาง Method Fields ของ Schema นั้นๆ
ในตัวอย่างนี้จะทำการเพิ่ม Field ใน Schema User ได้แก่ firstname,lastname และ age
Type
Type ที่ Framework นี้ support ได้แก่
- numeric type ต่างๆ เช่น int, uint8, float64 etc.
- string
- bool
- time.Time
- UUID
- []byte (เฉพาะ SQL)
- JSON (เฉพาะ SQL)
- ENUM (เฉพาะ SQL)
- Other (เฉพาะ SQL)
ID Field
ID เป็น default field ของทุก schema ไม่จำเป็นต้องเพิ่ม Field นี้เข้าไป โดยเราสามารถ Config ID Field ได้
ในตัวอย่างด้านบนเป็นการ Config ให้ field id ของ user มี type เป็น uuid
Database Type
ent จะมีการกำหนด Default Database Type ให้ทุก Type ของ Field ตามชนิดของ Database ไว้อยู่แล้ว แต่เราสามารถกำหนด Database Typeให้แต่ละ Field เองได้ด้วย Method SchemaType
โดยในตัวอย่างจะเป็นการเปลี่ยน type ของ column age ใน database postgres เป็น เป็น numeric แทน type เดิมที่เป็น int8
Go Type
นอกจาก Database type เราสามารถใช้ Method GoType เพื่อกำหนด type ของ go ในแต่ละ Field เองได้
ตัวอย่างนี้เป็นการเปลี่ยน type ของ lastname ที่เดิมเป็น string ให้เป็น sql.NullString แทน ซึ่งทำให้กรณีที่จะจัดการ Field นี้ต้องใช้ type เป็น lastname แทน แบบนี้
Default Value
Method Default และ UpdateDefault สามารถใช้กำหนดค่า Default ของ Field ได้เพื่อเป็นการกำหนดค่านั้นอัตโนมัติ ทุกครั้งที่มีการ Create หรือ Update Entity
ซึ่งตัวอย่างนี้เป็นการกำหนดค่า Default ของ field update_at ให้เป็นเวลาปัจจุบันตอนที่มีการ Create หรือ Update
Optional
โดยปกติแล้ว Field ทุก Field ใน Schema จะถูกกำหนดเป็น required field ซึ่งเราสามารถเปลี่ยนเป็น Optional Field ได้ด้วย Optional Method
Storage Key
Storage Key ใช้สำหรับกำหนด Column Name ใน Database สำหรับ Field นั้น
ตัวอย่างนี้เป็นการเปลี่ยนชื่อ Column ของ id เป็น userid แทน
เนื้อหาในเรื่องของ Field ก็จบเท่านี้ครับ ต่อไปเป็นเรื่องของ Edge
Edge
Edge คือ Relation ระหว่าง Schema โดย Method ที่ใช้ในการกำหนด Edge คือ edge.To และ edge.From โดย edge.To จะเป็นการสร้าง Relation ส่วน edge.From จะเป็นการสร้าง back-reference สำหรับใช้อ้างถึง Relation
ก่อนอื่นก็สร้าง Schema เพิ่มอีก 1 Schema
go run entgo.io/ent/cmd/ent init Pet
จากนั้นเพิ่ม Edge ให้กับ User และ Pet
จากตัวอย่างนี้ เป็นการสร้าง Edge pets ขึ้นที่ Schema User และสร้าง back-reference ชื่อ owner ที่ Schema Pet เพื่อให้โยงไปถึง User จาก Pet ได้
ซึ่ง Method Ref เป็นตัวกำหนด Edge ที่จะใช้เชื่อมโยงด้วย
ส่วน Method Unique จะเป็นตัวกำหนดรูปแบบของ Relation ซึ่งต่อไปจะเป็นตัวอย่างการกำหนด Relation รูปแบบต่างๆ
One-to-One
สร้าง Schema ใหม่ ชื่อ Card และเพิ่ม Edge ไปใน Schema User และ Card
ในการสร้าง Relation แบบ One-to-One ทำได้โดยเพิ่ม Method Unique ที่ทั้งสอง Schema เพื่อกำหนดให้แต่ละ Entity ของ Schema ไม่สามารถมี Edge ซ้ำกันได้
จากนั้นลองเพิ่มข้อมูล แล้วก็ Query ดู
ในตัวอย่างนี้ทำอะไรไปบ้าง ?
เริ่มจาก Create Entity ของ User แล้วก็ Card ขึ้นมาอย่างละ 1 โดยให้ User นี้เป็นเจ้าของ Card จากนั้นก็ Query ข้อมูล โดย Query Card ผ่าน User ด้วย Method QueryCard และ Query User ผ่าน Card ด้วย Method QueryOwner
ผลลัพธ์ที่ได้ ก็จะเป็นไปตามรูปด้านล่าง
One-to-Many
ความสัมพันธ์แบบ One-to-Many ทำได้โดยเพิ่ม Unique เข้าไปในฝั่งที่ต้องการให้เป็น Many
จากตัวอย่างนี้เพิ่ม Method Unique() ที่ owner ของ Pet ทำให้ Pet แต่ละตัวมีเจ้าของได้คนเดียว
จากตัวอย่างเป็นการสร้าง Pet มาสองตัวแล้วก็สร้าง User พร้อมกับเพิ่ม Pet เข้าไป จากนั้นก็ลอง Query และ Print ค่าออกมาดู
ผลลัพธ์ที่ได้ :
Many-to-Many
สร้าง Schema ชื่อ Group ขึ้นมาใหม่
วิธีสร้าง Relation แบบ Many-to-Many คือไม่ต้องใช้ Method Unique ทั้งสองฝั่งเลย
ตัวอย่างนี้เป็นการสร้าง Group และ User ขึ้นมา อย่างละ 2 และลอง Query Group ของแต่ละ User ดู
ผลลัพธ์ที่ได้ :
การสร้าง Relation แบบต่างๆก็จบลงเท่านี้ครับ ต่อไปเป็นเรื่องของ CRUD API
CRUD API
จากตัวอย่างหลายๆอันข้างบน เราก็ได้เห็นการใช้ฟังก์ชัน CRUD ไปแล้วบ้างนะครับ ในหัวข้อนี้เราจะมาพูดถึงวิธีการเขียน CRUD กัน ซึ่งจาก Command ด้านล่าง
go generate ./ent
ent จะทำการ generate method ต่างๆในการทำ CRUD มาให้ซึ่ง method ในแต่ละ Schema ก็จะแตกต่างกันตาม Field หรือ edge ใน Schema นั้นๆ
เรามาดูตัวอย่างการใช้ CRUD API กัน โดยข้างล่างนี้จะเป็นข้อมูล Schema ที่ใช้ในตัวอย่างนี้
Create
การ Create ทำได้โดยใช้ method create ของ schema นั้นๆแล้วตามด้วย method สำหรับกำหนดค่า Field ต่างๆใน Schema แล้วจบด้วย method Save หรือ SaveX ซึ่ง Save จะ return error ส่วน SaveX จะ panic ถ้ามี error
ผลลัพธ์ที่ได้ :
Update
Method ที่ใช้ Update มีสองแบบ คือ UpdateOne และ Update โดย UpdateOne จะคืนค่าเป็น Schema นั้น ส่วน Update จะคืนค่าเป็นจำนวน row ที่ถูก update
Query
เราสามารถ Query ได้หลายแบบไม่ว่าจะเป็น Query ผ่าน Schema โดยตรงหรือ Query ผ่าน Edge ของ Schema อื่น และสามารถเพิ่มเงื่อนไขในการ Query ได้ผ่าน Method Where
จากตัวอย่างจะเห็นว่าถ้า Query Pet แบบธรรมดาจะไม่สามารถดูข้อมูลของ Owner ได้ต้องเพิ่ม Method With เข้าไปด้วยจึงจะสามารถดูข้อมูลผ่าน Edge Owner ได้
Delete
ตัวอย่างนี้คือการลบ User แบบ 1 User และนี่คือผลลัพธ์ที่ได้
ก่อนลบ:
หลังลบ:
ส่วนตัวอย่างนี้คือการลบด้วยเงื่อนไข
เป็นการลบ User ที่มีอายุมากกว่าหรือเท่ากับ 30 โดย ผลลัพธ์ที่ได้
ก่อนลบ:
หลังลบ:
ครับ ก็จบไปแล้วนะครับสำหรับวิธีการจัดการ Database Model ด้วย Ent ซึ่งเนื้อหานี้เป็นเพียงพื้นฐานของการใช้งาน Framework นี้เท่านั้น ถ้าต้องการที่จะศึกษาเพิ่มเติมสามารถเข้าไปศึกษาได้ที่
ส่วน link นี้ เป็น git ที่รวมตัวอย่าง code ที่ใช้ในบทเรียนนี้
สามารถติดตามบทความและข่าวสารอื่นๆได้ที่ https://www.facebook.com/sirisoft และเพื่อนๆคนไหนสนใจอยากมา Dev ด้วยกันสามารถสมัครและทักสอบถาม HR กันมาได้นะครับ https://lin.ee/ms8vit4 ขอบคุณครับ