มาทำ Full Text Search ให้ Firebase Realtime Database ด้วย Cloud Function และ Elastic Search กันเถอะ

Patchara Rojanadickun
Firebase Thailand
Published in
3 min readOct 16, 2017

หากใครเคยได้ลองใช้เจ้า Firebase มาบ้างแล้วคงต้องยอมรับว่ามันเป็น platform ที่ทรงพลังมาก ด้วยความสามารถที่ทำให้เราพัฒนา application ได้ภายในไม่กี่อึดใจ (เว่อร์ตั้งแต่ต้นเรื่องเลยทีเดียว) เนื่องจาก service ที่ Firebase ให้นั้นค่อนข้างเรียกว่าครบมากเลยทีเดียว ไม่ว่าจะเป็นเรื่องของการ Authentication, Storage, Hosting หรือแม้แต่ Realtime Database (พระเอกของเราในวันนี้)

แต่หลังจากพัฒนาไปได้ซักระยะนึง ทำให้ข้อมูลมีขนาดมากขึ้นๆ ทำให้รู้ว่าการ search ใน Realtime Database นั้นไม่ใช่เรื่องง่ายเลย (แต่ใน Firestore เจ๋งขึ้นเยอะเลยนะ) แต่ในบทความนี้จะขอพูดถึง case ที่ใช้ Realtime Database ละกัน

SELECT * FROM somewhere WHERE soulmate LIKE ‘%CherprangBNK48%’

หากใครเคยใช้ SQL มาก่อนคงคุ้นเคยกับคำสั่งราวๆนี้มาแล้ว (ใครรันคำสั่งข้างบนเจอก็มาบอกผมด้วยนะ 55555)

ซึ่งถ้าหากใครใช้ RDB อยู่แล้วก็คงต้องผิดหวัง เนื่องจากเราไม่สามารถรันหรือใช้คำสั่งอะไรแบบนี้ได้เนี่ยสิ T T

ด้วยเหตุนี้คงต้องหาพระเอกขี่ม้าขาวมาช่วยให้เราสามารถ indexing สิ่งที่เราต้องการจะหาได้ ดังนั้นจะขอแนะนำเจ้า Elasticsearch

ซึ่งเป็น tools สุดน่ารักที่จะช่วยให้เราทำการ index สิ่งที่เราต้องการจะหาได้โดยเขียน code แค่ไม่กี่บรรทัดเท่านั้น!!! งั้นก็อย่ารอช้า รีบสร้าง project ใน Firebase ให้เร็วไว~~

ถึงแม้เราจะยอมรับว่า Firebase นี้เป็น platform ที่ดีเลิศประเสริฐศรีมณีเด้งแค่ไหน แต่ก็แอบมีความขี้งกอยู่นิดๆ เนื่องจากมันจะไม่ยอมให้เรา request ไป connection นอกอื่นๆเลยถ้าหากว่าเราไม่ “เปย์” มันก่อนนั่นเอง…

แต่ก็ช่างเถอะเพราะ Google Cloud Platform นั้นแจก credit ให้เราใช้ “ฟรีๆ” ถึง 300$ ด้วยกัน และข่าวดีคือสามารถใช้ร่วมกับ Firebase ได้ด้วย *o* (สมัครสิรอไรอยู่ https://console.cloud.google.com/freetrial ) หลังจากที่ไปเอาของฟรีกันมาแล้ว ก็ได้เวลาเปย์ไอเจ้า Firebase ซะที่… เลือกเป็น Blaze plan นะครับ

หลังจากที่เลือกเสร็จแล้วก็ได้เวลา setup เจ้าพระเอกของเรา elasticsearch นั่นเอง

เข้าไปที่ Google Cloud Console ตาม https://console.cloud.google.com/ แล้วเลือก Cloud Launcher จาก sidebar ด้านข้าง หลังจากนั้นหา elasticsearch

ขอเลือกตัว Bitnami มาใช้ละกันครับ (ไม่ใช้เพราะอะไร มันถูกสุดละ งกจริงๆ~~)

หลังจากกด LAUNCH ไปแล้ว ก็เข้าไป setup มันได้เลยตามนี้

เลือก Machine type เป็น micro พอครับ งบน้อยใช้แต่พอตัว~~ หลังจากนั้นก็กดสร้างได้เลย… ด้วยความไวของ GCP มันสามารถสร้างได้อย่างรวดเร็ว นับ 1 ถึง 3 ล้าน (ยืมมุกพี่ Jirawatee 🔥 มาใช้หน่อยนะครับ 55555)

เราก็จะได้หน้าตาอะไรแบบนี้ออกมา ซึ่งมี 3 ตัวหลักๆเลยที่ต้องใช้คือ Site address / Admin user และ Admin password ซึ่ง ทดไว้ในใจก่อนนะเดี๋ยวกลับมาใช้

หลังจากที่เรา setup เจ้านี่เสร็จแล้ว ก็ต้องทำการสอนเจ้า elasticsearch ให้มันรู้ว่าเราจะทำ mapping ข้อมูลอะไร ซึ่งสามารถทำได้ผ่าน HTTP Request นั่นเอง แต่เราสามารถใช้ Chrome Sense extension ตัวนึงชื่อว่า Sense ได้นะครับ

ด้านบนเป็นตัวอย่างทำ mapping ที่เราจะใช้ในตัวอย่างนี้กัน ใครจะปรับแต่งอะไรก็สามารถเข้าไปอ่าน document ของ elasticsearch ได้ครับ ในที่นี้ขอเอาง่ายๆไปก่อน 55555

หลังจากที่สอนมันเสร็จแล้วก็ได้เวลาพระเอกคนที่สองที่ชื่อว่า Cloud Function มาช่วยอีกแรง ซึ่งก่อนอื่นเลยเราต้อง setup Firebase tools ก่อน

> npm install -g firebase-tools

หลังจากนั้นเราก็ต้องเริ่มใช้งานเจ้าตัว cloud function

> firebase init functions

โดยให้เลือกเป็น project เดียวกับที่ทำอยู่

ในที่นี้จะขอไม่พูดถึงความสามารถของ Cloud Function ละกันครับ ถ้าหากใครยังไม่คุ้นเคยกับมัน แนะนำให้ไปอ่าน blog ของพี่ตี๋ Jirawatee 🔥 ดูก่อนได้ ตามนี้

เอาหล่ะมาเริ่มเขียนเจ้าตัว cloud function กันดีกว่า

ก่อนอื่นในการที่จะให้มันติดต่อกับตัว elasticsearch เราจำเป็นต้องลง dependencies เพิ่มบางตัว

> npm install --save request request-promise lodash

ถ้าหากเสร็จแล้วก็ใส่ code ตามนี้เลย

ซึ่งไอเจ้าตัว username และ password แล้วก็ url เราจะใช้ Firebase CLI เพื่อ config มันลงไป

> firebase functions:config:set elasticsearch.username=user> firebase functions:config:set elasticsearch.password=my_password> firebase functions:config:set elasticsearch.url=http://x.x.x.x/elasticsearch/

ซึ่งค่าทั้งสามตัวนี้มันคือสิ่งที่เราทดไว้ในใจจากขั้นตอนสร้าง elasticsearch บน GCP ด้านบนนั่นเอง (ใครจำไม่ได้ก็เลื่อนขึ้นไปดูเอานะ)

หลังจากเสร็จแล้วก็ง่ายๆ

> firebase deploy --only functions

ซึ่งถ้าไม่มีปัญหาอะไรจะได้หน้าสวยๆแบบนี้

เอาหล่ะ มาถึงขั้นสุดท้ายละ เรามา import data เพื่อให้ database trigger ทำงานกันดีกว่า ด้วยความขี้เกียดขั้นสุด ในที่นี้จะขอให้ sample data ที่ทาง Firebase มีเลยละกัน ไปโคลนได้เลยจากที่นี่

หลังจากนั้นก็กด import data เข้าไปใน RDB

ซึ่งถ้าไม่ติดอะไรก็จะได้ข้อมูลสวยๆแบบนี้

ทีนี้หลังจากเราได้ตรงนี้แล้ว ลองไปเช็คดูกันว่า cloud function ทำงานตามที่เราหวังไหม

ซึ่งถ้าไม่ติดอะไรมันควรจะออกมาหน้าตาแบบนี้นะ 55555

สุดท้ายเราก็ลองใช้เจ้า Sense เพื่อ test กันว่าสามารถยิง REST เพื่อ query จาก elasticsearch ได้มั้ย

ซึ่งถ้าหากไม่ติดอะไรก็จะได้ข้อมูลสวยงามเช่นนี้ ซึ่งถ้าหากใครจะไปปรับแต่งวิธีการ indexing ยังไงก็ตามศรัทธากันเลยครับ lols

ในบทความนี้คงไม่ได้พูดลง detail ของ code ที่เขียนด้วย node ต่างๆ ซึ่งหาอ่านได้ตาม github แล้วนำไปต่อยอดกันเองได้เลยครับ Happy Coding~~~

--

--