Node-RED - ตอนที่ 3 - Connect MySQL Database และตัวอย่างการใช้งาน
ตอนนี้เรามาทำให้ Node-RED ติดต่อกับ Database ได้กัน ถ้าถามว่าทำไมต้องต่อ Database ก็เพราะในบางงานเราอยากจำข้อมูลบางอย่างที่ยิงมาที่ Server เช่น เราอยากให้ Return Error : Duplicate กับ Transaction ที่มีเลข Reference ซ้ำเช่นตัวอย่างด้านล่าง
1 |
|
ซึ่งถ้าเราไม่เก็บข้อมูลไว้ว่า transactionRef ไหนใช้ไปแล้วบ้างเราจะไม่สามารถ Return Error Duplicate กลับไปให้ได้เลย ดังนั้นเราเลยต้องทำตัวที่เก็บข้อมูลซึ่งตัวเก็บข้อมูลที่เป็นที่นิยมก็คือ MySql นั่นเอง
ลง Node ที่ใช้เชื่อมต่อกับ Database
สามารถทำตามภาพด้านล่างได้เลย
ทำการ set ค่าให้ node-mysql
ส่วนนี้จะเป็นการทำการ config ให้ node สามารถเชื่อมต่อกับ Database ได้ โดยมีขั้นตอนดังต่อไปนี้
ในส่วนนี้คือการ Config เกี่ยวกับ Database
Host : ที่อยู่ของ database ของผมคือ 192.168.56.101
Port : Port ของ Database ของผมคือ 3306
User : User ที่ใช้ Login เข้า Database
Pass : Pass ที่ใช้ Login เข้า Database
Database : Database ที่ต้องการใช้งาน ของผมคือ Database ที่ชื่อ Node red
จากนั้นกด Deploy ถ้าเชื่อมต่อสำเร็จตัว node จะขึ้นคำว่า connected
สร้าง Table : payment_transaction เพื่อเก็บข้อมูล
ให้นำ sql script ที่สร้าง table ด้านล่างไปสร้าง table
1 | CREATE TABLE `payment_transaction` ( |
ส่ง Query ไปให้ Database ทำงาน
สั่ง Insert
ตัว node mysql นั้นจะรับคำสั่ง SQL เพื่อส่งไป Database ผ่าน msg.topic โดยถ้าสมมติจะ INSERT ข้อมูลลง Database ด้วยคำสั่ง
1 | INSERT INTO payment_transaction VALUES(NULL, 'TX00001'); |
เราก็สามารถ set ค่า msg.topic ด้วย SQL ด้านบนได้เลย โดยเราจะใช้ Node : Inject ในการส่งค่า msg.topic เข้าไปตามภาพ
ทำการเลือก Node : Inject (Node Injdect นั้นจะทำการสร้าง object : msg ตามที่เรากำหนด ว่าง่ายๆ มีไว้สร้าง msg และส่งไปให้ node ต่อไป ส่วนใหญ่ inject จะมีไว้ใช้ทดลองว่าถ้าได้รับ msg แบบนี้ ตัว flow ของเรานั้นทำงานถูกต้องหรือไม่ )
ลาก Node : Inject เข้าไปใน Flow
ทำการเปิด Node : Inject และกำหนดค่าในส่วนของ Topic ด้วยคำสั่ง SQL ที่เราต้องการ
ทำการกด Done
ทำการลากเส้นเชื่อมระหว่าง inject กับ mysql
ทำการกด Deploy เพื่อ update ตัว node-RED
ทำการกดปุ่มที่ node inject เพื่อให้ inject ส่งค่า
จากนั้นลองไปดูที่ Database ก็จะพบว่าข้อมูลที่เราสั่ง Insert ไป
สั่ง Select
ในส่วนที่แล้วเราสามารถสั่งให้ Insert ข้อมูลได้แล้ว สิ่งที่ขาดอยู่คือการ select เพื่อหาข้อมูล ซึ่งก็ไม่ยากเลยเพราะเรารู้แล้วว่าตัว Node mysql รับคำสั่ง sql ผ่าน msg.topic เราก็แค่เปลี่ยนคำสั่ง INSERT เป็นคำสั่ง SELECT ก็สามารถทำการ SELECT ข้อมูลได้แล้ว โดยเราจะ SELECT ข้อมูลง่ายๆแบบ
1 | SELECT * FROM payment_transaction; |
ทำการแก้ไข msg.topic ของ node inject เป็น sql ที่เราต้องการ
ทำการกด Done
ทำการนำ Node : debug เข้ามาใน Flow จากนั้นลากเส้นเชื่อมระหว่าง node mysql กับ debug
กด Deploy เพื่อ Update ตัว NodeRed
ทำการกดปุ่มที่ Node inject เพื่อส่งค่าเข้าไป
ลองดูผลลัพธ์จากการ Debug
จากดูที่ช่อง Debug เราจะพบว่าตัว Node sql หลังจากได้รับคำสั่ง SELECT จากจะ Return ผลลัพธ์ SELECT ออกมาเป็น array ของ object ซึ่งแต่ละ object จะมีค่า key ตามการ select ซึ่งอันนี้เรา select * มันเลยได้ key เป็นชื่อ column
จากภาพจะเห็นว่าผลลัพธ์ที่ออกมาเป็น array ที่มี object เดียว เพราะใน database เรามี row อยู่ row เดียว
แล้วจะ Dynamic Query ยังไง
จากความรู้ที่จากหัวข้อที่แล้วพอจะคิดคร่าวได้ประมาณว่า รับ http request มาจากนั้นทำ Query select เพื่อหาข้อมูลว่ามี transactionRef ใน DB ไหม ถ้าไม่มีทำการ insert ข้อมูลลง DB และทำการ Return SUCCESS แต่ถ้ามีแล้วทำการ Return DUPLICATE ปัญหาคือเราจะทำให้คำสั่ง SQL ของเรา Dynamic ได้ยังไง
ภาพร่างคร่าวๆของ flow ที่จะทำ
คราวนี้เราจะ dynamic query ยังไง ตรงส่วนนี้เราทำได้ 2 วิธี
- เราใช้ node : function เพื่อทำการสร้าง msg.topic ด้วย code ที่เราต้องการ เช่น
1 | msg.topic = `SELECT * FROM payment_transaction WHERE transactionRef = '${msg.payload.transactionRef}'` |
ซึ่งเมื่อเราต่อ httpin เข้า function แล้วลอง debug จะเห็นว่าคำสั่ง sql ที่ msg.topic จะได้ค่าตาม transactionRef ที่รับมา
ซึ่งถ้าเราเอาลากเส้นต่อเข้าไปที่ node mysql เราก็จะสามารถ select ได้
- ใช้ binding param ของ node mysql
ตัว node mysql นั้นมี feaure binding param ให้เราโดยในส่วนของ msg.topic เรากำหนดสร้าง param ขึ้นมาเพื่อจะนำค่าไปแทนที่ได้เช่น
1 | INSERT INTO payment_transaction VALUES(NULL, :transactionRef); |
ซึ่งถ้าเรา set แบบนี้ตัว transaction จะกลายเป็น param เพื่อเอาค่าไปแปะ ซึ่งคำถามคือจะเอาค่าจากไหนไปแปะ คำตอบคือตัว node mysql จะเอาค่าจาก msg.payload ไปแปะให้ตัวอย่างเช่น ถ้า payload คือ
1 | { |
sql ที่จะได้คือ
1 | INSERT INTO payment_transaction VALUES(NULL, 'Tx000WASINEE'); |
โดยเราสามารถใช้ Node inject ทดสอบดูว่าสามารถทำได้จริงหรือไม่โดยทำการ Set ดังภาพ
ซึ่งเมื่อเราสั่งให้ Inject ทำงานและเข้าไปดูใน Database เราจะพบข้อมูล Tx000WASINEE อยู่ใน Database
เรามาสร้าง Flow ทั้งหมดกัน
จากความรู้ของเราทั้งหมดที่เราได้รู้มาเราจะมาสร้าง Flow ที่เราต้องการกันตอนแรก โดย Flow ของผมนั้นอาจจะเหมือนที่คุณเขียนก็ได้ เพราะเราอาจจะใช้คนละวิธี ใช้คน Component กัน ดังน้ันไม่ต้องตกใจถ้า Flow ของผมไม่เหมือน Flow ของคุณ
ภาพรวมของ Flow
Flow ของผมหน้าตาประมาณนี้เดี๋ยวผมจะลงรายละเอียดบางจุดเท่านั้น ส่วนจุดอื่นๆที่ผมอธิบายไปแล้วหรือคิดว่าง่ายนั้นผมจะข้ามไปเลย หากใครสนใจทั้ง Flow สามารถ Download ได้จากตรงนี้เลย Link อย่าลืมเปลี่ยน config ตรง node mysql ด้วยนะครับ
เตรียมค่าสำหรับ Select
ตรงนี้ผมจะเขียนเป็น Function โดยการทำการ copy ค่า payload ไปใส่ใน copyPayload ซึ่งที่ต้องทำแบบนี้นั้นต้องทำเพราะเวลาเราทำการ Select ผ่าน Node mysql แล้วจะทำให้ค่า payload นั้นหายไป ดังนั้นเราต้องทำการเก็บค่า payload ไว้เพื่อใช้ในการ Insert
1 | msg.copyPayload = msg.payload |
เช็คว่ามีค่าใน DB ไหม
อันนี้ตามภาพเลยว่ามีข้อมูลไหม ถ้ามีไปทางด้านบน ถ้าไม่มีก็ไปทางด้านล่าง
ย้ายค่า copyPayload ไปเป็น payload
มาลอง Test กันดูว่าใช้งานได้จริงไหม
เราจะทดลองยิงกันโดยเราจะยิงโดยใช้ Body ด้านล่างโดยจะลองยิงสองครั้งเพื่อดูว่าได้ Response แบบที่คิดไหมและใน DB ได้เก็บข้อมูลลงไปไหม
1 | { |
ลองยิงครั้งแรก
จากการยิงครั้งแรกจะเห็นว่ายิงแล้วได้ SUCCESS
ลองยิงครั้งที่สอง
จากการยิงครั้งนี้จะเห็นว่ายิงแล้วได้ DUPLICATE
ตรวจสอบ Database ว่ามีข้อมูลไหม
จากภาพจะเห็นว่ามีข้อมูลอยู่ใน Database จริงๆ
สรุป
สำหรับตอนนี้เราได้เรียนรู้วิธีที่จะให้ Node-RED ต่อกับ Database แล้ว โดยในตัวอย่างเราใช้ทั้ง SELECT และ INSERT ส่วน UPDATE นั้นก็ไม่น่าจะยากครับ ผมเชื่อว่าถ้าคุณทดลองทำตามที่ผมทำในตอนนี้ผมเชื่อว่าคุณจะสามารถทำการ UPDATE ได้แน่นอนครับ สำหรับตอนนี้ขอจบเพียงเท่านี้สวัสดีครับ