Node-RED - ตอนที่ 3 - Connect MySQL Database และตัวอย่างการใช้งาน

Node-RED - ตอนที่ 3 - Connect MySQL Database และตัวอย่างการใช้งาน

ตอนนี้เรามาทำให้ Node-RED ติดต่อกับ Database ได้กัน ถ้าถามว่าทำไมต้องต่อ Database ก็เพราะในบางงานเราอยากจำข้อมูลบางอย่างที่ยิงมาที่ Server เช่น เราอยากให้ Return Error : Duplicate กับ Transaction ที่มีเลข Reference ซ้ำเช่นตัวอย่างด้านล่าง

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

การส่งครั้งแรก

# Request

{
"transactionRef" : "TX00001"
}

# Response
{
"status" : "SUCCESS"
}


การส่งครั้งที่สอง

# Request

{
"transactionRef" : "TX00001"
}

# Response
{
"status" : "DUPLICATE"
}

ซึ่งถ้าเราไม่เก็บข้อมูลไว้ว่า 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
2
3
4
5
CREATE TABLE `payment_transaction` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`transactionRef` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

ส่ง 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 เข้าไปตามภาพ

  1. ทำการเลือก Node : Inject (Node Injdect นั้นจะทำการสร้าง object : msg ตามที่เรากำหนด ว่าง่ายๆ มีไว้สร้าง msg และส่งไปให้ node ต่อไป ส่วนใหญ่ inject จะมีไว้ใช้ทดลองว่าถ้าได้รับ msg แบบนี้ ตัว flow ของเรานั้นทำงานถูกต้องหรือไม่ )

  2. ลาก Node : Inject เข้าไปใน Flow

  3. ทำการเปิด Node : Inject และกำหนดค่าในส่วนของ Topic ด้วยคำสั่ง SQL ที่เราต้องการ

  4. ทำการกด Done

  1. ทำการลากเส้นเชื่อมระหว่าง inject กับ mysql

  2. ทำการกด Deploy เพื่อ update ตัว node-RED

  3. ทำการกดปุ่มที่ node inject เพื่อให้ inject ส่งค่า

จากนั้นลองไปดูที่ Database ก็จะพบว่าข้อมูลที่เราสั่ง Insert ไป

สั่ง Select

ในส่วนที่แล้วเราสามารถสั่งให้ Insert ข้อมูลได้แล้ว สิ่งที่ขาดอยู่คือการ select เพื่อหาข้อมูล ซึ่งก็ไม่ยากเลยเพราะเรารู้แล้วว่าตัว Node mysql รับคำสั่ง sql ผ่าน msg.topic เราก็แค่เปลี่ยนคำสั่ง INSERT เป็นคำสั่ง SELECT ก็สามารถทำการ SELECT ข้อมูลได้แล้ว โดยเราจะ SELECT ข้อมูลง่ายๆแบบ

1
SELECT * FROM payment_transaction;

  1. ทำการแก้ไข msg.topic ของ node inject เป็น sql ที่เราต้องการ

  2. ทำการกด Done

  1. ทำการนำ Node : debug เข้ามาใน Flow จากนั้นลากเส้นเชื่อมระหว่าง node mysql กับ debug

  2. กด Deploy เพื่อ Update ตัว NodeRed

  1. ทำการกดปุ่มที่ Node inject เพื่อส่งค่าเข้าไป

  2. ลองดูผลลัพธ์จากการ 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 วิธี

  1. เราใช้ node : function เพื่อทำการสร้าง msg.topic ด้วย code ที่เราต้องการ เช่น
1
2
msg.topic = `SELECT * FROM payment_transaction  WHERE transactionRef = '${msg.payload.transactionRef}'`
return msg;

ซึ่งเมื่อเราต่อ httpin เข้า function แล้วลอง debug จะเห็นว่าคำสั่ง sql ที่ msg.topic จะได้ค่าตาม transactionRef ที่รับมา

ซึ่งถ้าเราเอาลากเส้นต่อเข้าไปที่ node mysql เราก็จะสามารถ select ได้

  1. ใช้ 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
2
3
{
"transactionRef" : "Tx000WASINEE"
}

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
2
3
{
"transactionRef" : "TX-SUNISA"
}

ลองยิงครั้งแรก

จากการยิงครั้งแรกจะเห็นว่ายิงแล้วได้ SUCCESS

ลองยิงครั้งที่สอง

จากการยิงครั้งนี้จะเห็นว่ายิงแล้วได้ DUPLICATE

ตรวจสอบ Database ว่ามีข้อมูลไหม

จากภาพจะเห็นว่ามีข้อมูลอยู่ใน Database จริงๆ

สรุป

สำหรับตอนนี้เราได้เรียนรู้วิธีที่จะให้ Node-RED ต่อกับ Database แล้ว โดยในตัวอย่างเราใช้ทั้ง SELECT และ INSERT ส่วน UPDATE นั้นก็ไม่น่าจะยากครับ ผมเชื่อว่าถ้าคุณทดลองทำตามที่ผมทำในตอนนี้ผมเชื่อว่าคุณจะสามารถทำการ UPDATE ได้แน่นอนครับ สำหรับตอนนี้ขอจบเพียงเท่านี้สวัสดีครับ