
ในยุคดิจิทัลที่ข้อมูลหลั่งไหลเข้ามามหาศาล การค้นหาข้อมูลที่แม่นยำ รวดเร็ว และตรงกับความต้องการของผู้ใช้มากที่สุด ถือเป็นหัวใจสำคัญของความสำเร็จ ไม่ว่าจะเป็นเว็บไซต์อีคอมเมิร์ซที่ต้องการให้ลูกค้าหาสินค้าที่ถูกใจได้อย่างง่ายดาย ระบบจัดการเอกสารภายในองค์กรที่ต้องค้นหาข้อมูลสำคัญได้อย่างฉับไว หรือแม้แต่แอปพลิเคชันมือถือที่ต้องการมอบประสบการณ์การค้นหาที่เหนือกว่า การใช้ระบบค้นหาแบบเดิมๆ ที่พึ่งพาฐานข้อมูลเชิงสัมพันธ์ (RDBMS) อาจไม่เพียงพออีกต่อไปแล้วครับ บทความนี้จะพาคุณเจาะลึกถึงโลกของ Elasticsearch เครื่องมือทรงพลังที่จะช่วยให้คุณสร้างระบบค้นหาอัจฉริยะแบบ Full-text Search ที่ไม่เพียงแต่รวดเร็ว แต่ยังฉลาดและเข้าใจบริบทของการค้นหาได้อย่างแท้จริง พร้อมตัวอย่างและแนวทางปฏิบัติที่จะช่วยให้คุณเริ่มต้นใช้งานได้อย่างมั่นใจครับ
สารบัญ
- ทำความรู้จักกับ Full-text Search และปัญหาของการค้นหาแบบเดิม
- Elasticsearch คืออะไร? ทำไมต้อง Elasticsearch?
- สถาปัตยกรรมและส่วนประกอบสำคัญของ Elasticsearch
- การติดตั้งและเริ่มต้นใช้งาน Elasticsearch (เบื้องต้น)
- การสร้าง Index และการทำ Mapping
- การเพิ่ม, อัปเดต, ลบ Document ใน Elasticsearch
- หัวใจของการค้นหา: Query DSL ใน Elasticsearch
- Match Query: การค้นหาข้อความแบบ Full-text
- Match Phrase Query: ค้นหาวลีที่ตรงกัน
- Term Query: ค้นหาคำที่ตรงกันเป๊ะ
- Boolean Query (bool): การรวมเงื่อนไขการค้นหา
- Range Query: การค้นหาในช่วงค่า
- Wildcard และ Regexp Query: การค้นหาด้วยรูปแบบ
- Fuzzy Query: การค้นหาที่ทนต่อความผิดพลาด (Typo)
- Highlighting: การเน้นคำที่ค้นพบ
- การจัดอันดับความเกี่ยวข้อง (Relevance Scoring) และ Boost
- Aggregations: การวิเคราะห์ข้อมูลเชิงลึกและ Faceted Search
- Advanced Features เพื่อระบบค้นหาอัจฉริยะ
- การเปรียบเทียบ Elasticsearch กับ RDBMS และ Solr
- การดูแลรักษาและปรับแต่งประสิทธิภาพ (Performance Tuning)
- คำถามที่พบบ่อย (FAQ)
- สรุปและ Call-to-Action
ทำความรู้จักกับ Full-text Search และปัญหาของการค้นหาแบบเดิม
Full-text Search คืออะไร?
Full-text Search หรือ “การค้นหาข้อความเต็ม” คือกระบวนการที่ช่วยให้ผู้ใช้สามารถค้นหาคำหรือวลีที่ปรากฏอยู่ในเอกสารหรือข้อมูลจำนวนมากได้อย่างมีประสิทธิภาพ โดยไม่เพียงแค่จับคู่คำต่อคำแบบตรงไปตรงมา แต่ยังรวมถึงความสามารถในการเข้าใจบริบท, การจัดการกับคำพ้องความหมาย, การแก้ไขคำผิด (typo), การเรียงลำดับผลลัพธ์ตามความเกี่ยวข้อง (relevance) และการค้นหาคำที่ใกล้เคียงกันครับ
ลองนึกภาพการค้นหาสินค้าบนเว็บไซต์อีคอมเมิร์ซ หากคุณค้นหาคำว่า “โทรศัพท์มือถือ” ระบบ Full-text Search ที่ดีจะสามารถแสดงผลลัพธ์ของ “สมาร์ทโฟน”, “มือถือ”, “โทรศัพท์” หรือแม้แต่รุ่นของโทรศัพท์ที่คนส่วนใหญ่นิยมค้นหาได้ โดยจัดอันดับผลลัพธ์ที่เกี่ยวข้องมากที่สุดขึ้นมาก่อน นี่คือสิ่งที่เหนือกว่าการค้นหาแบบธรรมดาครับ
ข้อจำกัดของการค้นหาในฐานข้อมูลเชิงสัมพันธ์ (RDBMS)
สำหรับนักพัฒนาหลายท่าน RDBMS อย่าง MySQL, PostgreSQL หรือ SQL Server เป็นเครื่องมือหลักในการจัดเก็บและค้นหาข้อมูลมาโดยตลอด แต่เมื่อพูดถึง Full-text Search ที่แท้จริง RDBMS มีข้อจำกัดหลายประการครับ
-
ประสิทธิภาพ (Performance):
การใช้คำสั่ง
LIKE '%keyword%'ใน SQL เพื่อค้นหาข้อความเต็มนั้นมีประสิทธิภาพต่ำมาก โดยเฉพาะเมื่อข้อมูลมีขนาดใหญ่ เนื่องจากฐานข้อมูลต้องสแกนทุกแถวและทุกคอลัมน์ที่เกี่ยวข้อง ซึ่งใช้ทรัพยากรมากและใช้เวลานานครับ แม้บาง RDBMS จะมีฟังก์ชัน Full-text Search ในตัว (เช่น MySQL Full-Text Search, PostgreSQL pg_trgm) แต่ก็มักจะมีความสามารถจำกัด ไม่สามารถปรับแต่งได้หลากหลายเท่าที่ควร และอาจไม่เหมาะกับข้อมูลที่มีปริมาณมหาศาลหรือการค้นหาที่ซับซ้อนครับ -
ความเกี่ยวข้อง (Relevance):
RDBMS ส่วนใหญ่ไม่สามารถจัดอันดับความเกี่ยวข้องของผลลัพธ์ได้ดีนัก ผลลัพธ์ที่ได้มักจะเป็นการจับคู่แบบ “มีหรือไม่” เท่านั้น ไม่สามารถบอกได้ว่าเอกสารใดมีความเกี่ยวข้องกับคำค้นหามากกว่ากัน ทำให้ผู้ใช้ต้องเลื่อนหาข้อมูลที่ต้องการเอง ซึ่งเสียเวลาและลดประสบการณ์การใช้งานครับ
-
ความยืดหยุ่นและการวิเคราะห์ (Flexibility & Analysis):
การค้นหาใน RDBMS มักจะยึดติดกับโครงสร้างตารางและคอลัมน์ที่ตายตัว การค้นหาคำพ้องความหมาย การแก้ไขคำผิด การค้นหาแบบ Faceted Search (การกรองผลลัพธ์ตามหมวดหมู่ต่างๆ) หรือการวิเคราะห์ข้อมูลเชิงลึก (Aggregations) เป็นสิ่งที่ทำได้ยากหรือไม่สามารถทำได้เลยใน RDBMS ทั่วไปครับ
-
ความสามารถในการขยายตัว (Scalability):
เมื่อปริมาณข้อมูลและจำนวนผู้ใช้งานเพิ่มขึ้น การขยายระบบ RDBMS เพื่อรองรับการค้นหา Full-text ที่มีประสิทธิภาพมักเป็นเรื่องที่ซับซ้อนและมีค่าใช้จ่ายสูง การทำ Sharding หรือ Replication ใน RDBMS เพื่อการค้นหาอาจช่วยได้ในระดับหนึ่ง แต่ก็ยังคงมีข้อจำกัดเมื่อเทียบกับระบบที่ออกแบบมาเพื่อการนี้โดยเฉพาะครับ
ด้วยข้อจำกัดเหล่านี้ จึงเป็นที่มาของการมองหาระบบค้นหาเฉพาะทางที่ถูกออกแบบมาเพื่อจัดการกับ Full-text Search โดยเฉพาะ ซึ่งหนึ่งในเครื่องมือที่ได้รับความนิยมและทรงพลังที่สุดในปัจจุบันก็คือ Elasticsearch นั่นเองครับ
Elasticsearch คืออะไร? ทำไมต้อง Elasticsearch?
ภาพรวมของ Elasticsearch
Elasticsearch คือ Search Engine แบบกระจายตัว (Distributed) และ RESTful ที่ทำงานแบบเรียลไทม์ ครับ ถูกสร้างขึ้นบน Apache Lucene ซึ่งเป็นไลบรารีสำหรับ Full-text Search ที่มีประสิทธิภาพสูง Elasticsearch ออกแบบมาเพื่อจัดเก็บ จัดทำดัชนี (index) และค้นหาข้อมูลจำนวนมหาศาลได้อย่างรวดเร็วและยืดหยุ่น โดยข้อมูลที่จัดเก็บอยู่ในรูปแบบ JSON ทำให้สามารถรองรับข้อมูลที่มีโครงสร้าง (structured), ไม่มีโครงสร้าง (unstructured) และกึ่งโครงสร้าง (semi-structured) ได้อย่างดีเยี่ยมครับ
ลองนึกภาพว่าคุณมีข้อมูลมหาศาล ไม่ว่าจะเป็นบทความ, ข้อมูลสินค้า, บันทึกการทำงาน (log files), หรือข้อมูลผู้ใช้ Elasticsearch จะเข้ามาทำหน้าที่เป็นศูนย์กลางในการจัดเก็บและประมวลผลข้อมูลเหล่านี้ เพื่อให้คุณสามารถค้นหา, กรอง, และวิเคราะห์ข้อมูลเหล่านั้นได้อย่างรวดเร็วและชาญฉลาดครับ
เหตุผลที่ควรเลือกใช้ Elasticsearch
-
ความเร็วสูง (Blazing Fast):
Elasticsearch สามารถค้นหาข้อมูลจำนวนมหาศาลได้ในระดับมิลลิวินาที (milliseconds) ด้วยโครงสร้างข้อมูลแบบ Inverted Index ที่ถูกสร้างมาเพื่อการค้นหาโดยเฉพาะ ทำให้การค้นหาเป็นไปอย่างรวดเร็ว แม้ข้อมูลจะมีขนาดใหญ่ขึ้นเรื่อยๆ ครับ
-
ความสามารถในการขยายตัว (Scalability):
ออกแบบมาให้เป็นระบบแบบกระจายตัวตั้งแต่ต้น คุณสามารถเพิ่ม Node เข้าไปใน Cluster เพื่อเพิ่มขีดความสามารถในการจัดเก็บและประมวลผลข้อมูลได้อย่างง่ายดาย โดยไม่ต้องหยุดระบบ (horizontal scaling) ทำให้เหมาะสำหรับแอปพลิเคชันที่ต้องการความพร้อมใช้งานสูงและสามารถรองรับการเติบโตของข้อมูลได้ดีครับ
-
RESTful API:
การสื่อสารกับ Elasticsearch ทำได้ง่ายผ่าน RESTful API โดยใช้ JSON เป็นรูปแบบข้อมูล ทำให้สามารถเชื่อมต่อและพัฒนาแอปพลิเคชันได้ด้วยภาษาโปรแกรมเกือบทุกภาษาครับ
-
Full-text Search ที่ทรงพลัง:
ด้วยการที่อยู่บน Lucene ทำให้ Elasticsearch มีความสามารถ Full-text Search ที่ยอดเยี่ยม ทั้งการค้นหาคำ, วลี, การจัดการคำพ้องความหมาย, การแก้ไขคำผิด, การค้นหาแบบ Fuzzy, การจัดอันดับความเกี่ยวข้องของผลลัพธ์ และอื่นๆ อีกมากมายครับ
-
การวิเคราะห์ข้อมูลเชิงลึก (Aggregations):
นอกจากการค้นหาแล้ว Elasticsearch ยังมีความสามารถในการทำ Aggregations ที่ทรงพลัง ซึ่งช่วยให้คุณสามารถสรุป, วิเคราะห์, และสร้าง Dashboard จากข้อมูลได้อย่างรวดเร็วและยืดหยุ่น คล้ายกับคำสั่ง GROUP BY ใน SQL แต่มีประสิทธิภาพและยืดหยุ่นกว่ามากครับ
-
ระบบนิเวศที่สมบูรณ์ (Rich Ecosystem):
Elasticsearch เป็นส่วนหนึ่งของ Elastic Stack (เดิมคือ ELK Stack) ซึ่งประกอบด้วย Kibana (เครื่องมือ Visualization และ Dashboard), Logstash (เครื่องมือสำหรับรวบรวมและประมวลผลข้อมูล), และ Beats (เครื่องมือสำหรับส่งข้อมูล) ทำให้เป็นโซลูชันที่ครบวงจรสำหรับการจัดการข้อมูลและการวิเคราะห์ครับ
กรณีการใช้งานที่พบบ่อย
-
เว็บไซต์อีคอมเมิร์ซ:
สร้างระบบค้นหาสินค้าที่รวดเร็ว แม่นยำ พร้อมระบบกรอง (faceted search) และแนะนำสินค้า
-
ระบบจัดการเอกสาร/เนื้อหา:
ค้นหาบทความ, ข่าวสาร, เอกสารภายในองค์กรได้อย่างมีประสิทธิภาพ
-
การวิเคราะห์ Log และ Metric (ELK Stack):
ใช้รวบรวม, จัดเก็บ, ค้นหา, และวิเคราะห์ Log จาก Server, แอปพลิเคชัน, และอุปกรณ์เครือข่าย เพื่อตรวจสอบสถานะและแก้ไขปัญหา
-
ระบบ Business Intelligence (BI):
ใช้เป็นแหล่งข้อมูลสำหรับสร้าง Dashboard และรายงาน เพื่อให้ได้ Insight จากข้อมูลได้อย่างรวดเร็ว
-
ระบบรักษาความปลอดภัย (SIEM):
วิเคราะห์ข้อมูลความปลอดภัยแบบเรียลไทม์ เพื่อตรวจจับภัยคุกคาม
ด้วยคุณสมบัติเหล่านี้ Elasticsearch จึงเป็นตัวเลือกที่ยอดเยี่ยมสำหรับการสร้างระบบค้นหาอัจฉริยะและแพลตฟอร์มวิเคราะห์ข้อมูลในหลากหลายอุตสาหกรรมครับ อ่านเพิ่มเติมเกี่ยวกับกรณีศึกษาของ Elasticsearch
สถาปัตยกรรมและส่วนประกอบสำคัญของ Elasticsearch
การทำความเข้าใจสถาปัตยกรรมของ Elasticsearch เป็นสิ่งสำคัญในการใช้งานและปรับแต่งให้มีประสิทธิภาพสูงสุดครับ มาดูกันว่าส่วนประกอบหลักๆ มีอะไรบ้าง
Cluster และ Node
-
Cluster:
คือกลุ่มของ Node หนึ่งตัวหรือมากกว่าที่ทำงานร่วมกันเพื่อจัดเก็บและจัดการข้อมูลทั้งหมดในระบบครับ ทุก Node ใน Cluster จะสื่อสารกันเพื่อแบ่งปันข้อมูลและกระจายงาน Cluster มีชื่อเฉพาะเพื่อระบุตัวตน เช่น
"my-application-cluster" -
Node:
คือ Server หรือ Instance ที่รัน Elasticsearch อยู่ Node แต่ละตัวมีชื่อเฉพาะ (เช่น
"node-1") และมีบทบาทหน้าที่ที่แตกต่างกันได้ เช่น:- Master Node: ทำหน้าที่จัดการ Cluster ทั้งหมด เช่น การสร้าง/ลบ Index, การจัดการ Shard, การติดตามสถานะของ Node อื่นๆ
- Data Node: ทำหน้าที่จัดเก็บข้อมูล (Documents) และประมวลผลการค้นหา (search) และการรวบรวมข้อมูล (aggregation)
- Ingest Node: ทำหน้าที่ Pre-processing ข้อมูลก่อนจะถูกจัดเก็บเข้า Index
- Coordinating Node: รับคำร้องขอจากไคลเอนต์, ส่งต่อไปยัง Node ที่เกี่ยวข้อง, และรวบรวมผลลัพธ์กลับมา (ทุก Node สามารถทำหน้าที่นี้ได้)
ใน Cluster ขนาดเล็ก Node เดียวอาจทำหน้าที่ทุกอย่าง แต่ในระบบขนาดใหญ่ เราจะแยกบทบาทเพื่อให้เกิดประสิทธิภาพและความเสถียรสูงสุดครับ
Index และ Document
-
Index:
เป็นเหมือนฐานข้อมูล (Database) ในโลกของ RDBMS ครับ Index คือคอลเลกชันของ Document ที่มีความเกี่ยวข้องกันทางตรรกะ (logical grouping) ซึ่งถูกออกแบบมาให้มีโครงสร้าง Mapping ที่คล้ายกัน เช่น Index สำหรับสินค้า, Index สำหรับผู้ใช้, Index สำหรับ Log ของ Server ครับ
การสร้าง Index เป็นจุดเริ่มต้นของการจัดเก็บข้อมูลใน Elasticsearch ตัวอย่างเช่น คุณอาจมี Index ชื่อ
products,users, หรือlogs-2023-10ครับ -
Document:
คือหน่วยข้อมูลพื้นฐานที่จัดเก็บใน Elasticsearch เป็นเหมือนแถว (Row) ใน RDBMS ครับ แต่ละ Document เป็นโครงสร้างข้อมูลแบบ JSON ที่มีความยืดหยุ่นสูง ประกอบด้วย Field ต่างๆ และมี ID ที่ไม่ซ้ำกันภายใน Index นั้นๆ ครับ
{ "id": "SKU001", "name": "สมาร์ทโฟน X Pro", "description": "สมาร์ทโฟนประสิทธิภาพสูง พร้อมกล้อง AI และแบตเตอรี่ทนทาน", "price": 19999.00, "category": ["Electronics", "Mobile Phones"], "brand": "TechCorp", "stock": 150, "available": true, "tags": ["mobile", "smartphone", "android", "techcorp"], "created_at": "2023-10-26T10:00:00Z" }จะเห็นว่า Document นี้สามารถมี Field ที่เป็นสตริง, ตัวเลข, บูลีน, อาร์เรย์ หรือแม้แต่วันที่ได้ครับ
-
Field:
คือคู่ของชื่อและค่า (key-value pair) ภายใน Document เช่น
"name": "สมาร์ทโฟน X Pro"โดยnameคือ Field และ"สมาร์ทโฟน X Pro"คือค่าของ Field นั้นครับ
Shard และ Replica
นี่คือหัวใจสำคัญที่ทำให้ Elasticsearch สามารถขยายตัวและมีความทนทานต่อความผิดพลาดได้ครับ
-
Shard:
เมื่อคุณสร้าง Index ขึ้นมา Elasticsearch จะแบ่ง Index นั้นออกเป็นส่วนย่อยๆ ที่เรียกว่า Shard ครับ แต่ละ Shard เป็น Lucene Index ที่ทำงานได้อย่างอิสระและเป็นหน่วยพื้นฐานในการจัดเก็บข้อมูลจริง Shard สามารถถูกกระจายไปเก็บอยู่บน Node ต่างๆ ใน Cluster ได้ ซึ่งทำให้สามารถประมวลผลการค้นหาแบบขนาน (parallel processing) และเพิ่มความสามารถในการขยายตัว (scalability) ครับ
เราเรียก Shard ที่เก็บข้อมูลต้นฉบับว่า Primary Shard ครับ
-
Replica Shard (Replica):
คือสำเนาของ Primary Shard ครับ Replica Shard มีประโยชน์หลักๆ สองประการคือ:
- ความทนทานต่อความผิดพลาด (Fault Tolerance): หาก Primary Shard บน Node ใด Node หนึ่งล้มเหลว Replica Shard สามารถเข้ามาทำหน้าที่แทนได้ทันที ทำให้ข้อมูลไม่สูญหายและระบบยังคงทำงานได้ต่อเนื่องครับ
- ประสิทธิภาพการค้นหา (Search Performance): สามารถใช้ Replica Shard ในการประมวลผลคำค้นหาได้เช่นกัน ทำให้ Cluster สามารถรองรับปริมาณการค้นหาที่สูงขึ้นได้ครับ
คุณสามารถกำหนดจำนวน Primary Shard และ Replica Shard ได้ในตอนสร้าง Index ครับ โดยทั่วไปมักจะกำหนดให้มีอย่างน้อย 1 Replica เพื่อความทนทานครับ
Mapping และ Analysis
-
Mapping:
คือการกำหนดโครงสร้างและประเภทข้อมูลของ Field ต่างๆ ใน Document ที่จะถูกจัดเก็บใน Index ครับ คล้ายกับ Schema ใน RDBMS แต่มีความยืดหยุ่นกว่า Mapping บอก Elasticsearch ว่าควรจัดเก็บและ Index ข้อมูลในแต่ละ Field อย่างไร เช่น Field
nameควรเป็นtextเพื่อการค้นหาแบบ Full-text, Fieldpriceควรเป็นfloatเพื่อการคำนวณ, หรือcreated_atควรเป็นdateครับหากคุณไม่ได้กำหนด Mapping เอง Elasticsearch จะพยายามเดาประเภทข้อมูลให้โดยอัตโนมัติ (Dynamic Mapping) แต่การกำหนด Explicit Mapping จะช่วยให้คุณควบคุมการจัดเก็บและการค้นหาได้อย่างแม่นยำยิ่งขึ้นครับ
-
Analysis:
คือกระบวนการที่เกิดขึ้นกับ Field ประเภท
textก่อนที่จะถูกจัดเก็บใน Inverted Index เพื่อให้การค้นหาแบบ Full-text มีประสิทธิภาพและชาญฉลาดครับ กระบวนการ Analysis ประกอบด้วย:- Character Filters: ประมวลผลข้อความดิบ (raw text) ก่อน เช่น ลบแท็ก HTML, แปลงอักขระพิเศษ
- Tokenizer: แบ่งข้อความออกเป็นคำย่อยๆ หรือ “โทเค็น” (tokens) เช่น “สมาร์ทโฟนประสิทธิภาพสูง” อาจถูกแบ่งเป็น [“สมาร์ทโฟน”, “ประสิทธิภาพ”, “สูง”]
- Token Filters: ปรับแต่งโทเค็นที่ได้ เช่น แปลงเป็นตัวพิมพ์เล็ก (lowercase), ลบ Stop Words (คำทั่วไปที่ไม่มีความหมาย เช่น “และ”, “หรือ”), การ Stemming (ลดคำให้อยู่ในรูปรากศัพท์ เช่น “running” เหลือ “run”) หรือการจัดการคำพ้องความหมาย (synonyms) ครับ
ผลลัพธ์ของกระบวนการ Analysis คือ Inverted Index ที่ถูกใช้ในการค้นหา ซึ่งทำให้ Elasticsearch ค้นหาได้อย่างรวดเร็วและชาญฉลาดครับ การเลือก Analyzer ที่เหมาะสม (โดยเฉพาะสำหรับภาษาไทย) มีความสำคัญอย่างยิ่งต่อคุณภาพของผลลัพธ์การค้นหาครับ
เมื่อเข้าใจส่วนประกอบเหล่านี้แล้ว คุณจะสามารถออกแบบและจัดการ Cluster Elasticsearch ของคุณได้อย่างมีประสิทธิภาพสูงสุดครับ
การติดตั้งและเริ่มต้นใช้งาน Elasticsearch (เบื้องต้น)
มาเริ่มต้นติดตั้ง Elasticsearch และ Kibana กันครับ บทความนี้จะเน้นการติดตั้งบนระบบปฏิบัติการทั่วไป (Linux/macOS) ซึ่งคล้ายคลึงกับการรันบน Windows ด้วยเช่นกันครับ
ข้อกำหนดเบื้องต้น
Elasticsearch ต้องการ Java Development Kit (JDK) หรือ Java Runtime Environment (JRE) เวอร์ชันที่รองรับครับ โดยปกติแล้ว Elasticsearch เวอร์ชันใหม่ๆ มักจะรวม JDK มาให้ในแพ็กเกจแล้ว แต่ถ้าไม่ คุณอาจต้องติดตั้งเอง ตรวจสอบเวอร์ชันที่แนะนำได้จากเว็บไซต์ทางการของ Elastic ครับ
การติดตั้ง Elasticsearch
เราจะใช้วิธีดาวน์โหลดและแตกไฟล์ ซึ่งเป็นวิธีที่ง่ายที่สุดสำหรับการเริ่มต้นใช้งานครับ
-
ดาวน์โหลด Elasticsearch:
ไปที่เว็บไซต์ Elasticsearch Download และดาวน์โหลดไฟล์ตามระบบปฏิบัติการของคุณ (เช่น .tar.gz สำหรับ Linux/macOS, .zip สำหรับ Windows) ครับ
-
แตกไฟล์:
แตกไฟล์ที่ดาวน์โหลดมาไปยังตำแหน่งที่คุณต้องการติดตั้ง เช่น
/usr/local/elasticsearchหรือC:\elasticsearchครับ# สำหรับ Linux/macOS tar -xzf elasticsearch-8.x.x-linux-x86_64.tar.gz mv elasticsearch-8.x.x /usr/local/elasticsearch -
เรียกใช้งาน Elasticsearch:
เข้าไปยังไดเรกทอรีของ Elasticsearch และรันสคริปต์
elasticsearchครับ# สำหรับ Linux/macOS cd /usr/local/elasticsearch ./bin/elasticsearch# สำหรับ Windows (ใน Command Prompt หรือ PowerShell) cd C:\elasticsearch .\bin\elasticsearch.batเมื่อรันแล้ว คุณจะเห็นข้อความ Log มากมายใน Terminal ซึ่งแสดงว่า Elasticsearch กำลังเริ่มต้นทำงานครับ โดยปกติจะรันบนพอร์ต 9200 ครับ
หมายเหตุ: ใน Elasticsearch เวอร์ชัน 8 ขึ้นไป จะมีการเปิดใช้งาน Security โดยค่าเริ่มต้น ซึ่งอาจต้องตั้งค่า User/Password หรือ Certificate หากต้องการเข้าถึงจากภายนอก สำหรับการทดสอบเบื้องต้น คุณอาจปิดการตั้งค่าความปลอดภัยชั่วคราวได้ในไฟล์
config/elasticsearch.yml(แต่ไม่แนะนำสำหรับการใช้งานจริง) หรือทำตามขั้นตอนการตั้งค่า Security ที่ Elasticsearch แนะนำครับ
การติดตั้ง Kibana (เครื่องมือจัดการ UI)
Kibana เป็นเครื่องมือสำหรับ Visualization และ Management UI ที่ช่วยให้คุณสามารถโต้ตอบกับ Elasticsearch ได้ง่ายขึ้นครับ
-
ดาวน์โหลด Kibana:
ไปที่เว็บไซต์ Kibana Download และดาวน์โหลดไฟล์เวอร์ชันที่ตรงกับ Elasticsearch ของคุณครับ (สำคัญมากที่ต้องใช้เวอร์ชันเดียวกัน)
-
แตกไฟล์:
แตกไฟล์ที่ดาวน์โหลดมาไปยังตำแหน่งที่ต้องการ เช่น
/usr/local/kibanaครับ# สำหรับ Linux/macOS tar -xzf kibana-8.x.x-linux-x86_64.tar.gz mv kibana-8.x.x /usr/local/kibana -
เรียกใช้งาน Kibana:
เข้าไปยังไดเรกทอรีของ Kibana และรันสคริปต์
kibanaครับ# สำหรับ Linux/macOS cd /usr/local/kibana ./bin/kibana# สำหรับ Windows cd C:\kibana .\bin\kibana.batเมื่อรันแล้ว Kibana จะเริ่มต้นทำงาน โดยปกติจะรันบนพอร์ต 5601 ครับ
-
เข้าถึง Kibana UI:
เปิดเว็บเบราว์เซอร์ของคุณแล้วไปที่
http://localhost:5601คุณจะเห็นหน้า UI ของ Kibana ซึ่งสามารถใช้ในการจัดการและสำรวจข้อมูลใน Elasticsearch ได้ครับ หากคุณเปิด Security ไว้ใน Elasticsearch, Kibana จะแนะนำให้คุณใส่รหัสผ่านและโทเค็นเพื่อเชื่อมต่อครับ
ตรวจสอบสถานะ Cluster
เมื่อ Elasticsearch ทำงานอยู่ คุณสามารถตรวจสอบสถานะของ Cluster ได้ง่ายๆ ผ่าน RESTful API โดยใช้เครื่องมืออย่าง curl หรือใน Kibana Dev Tools ครับ
curl -X GET "localhost:9200/_cat/health?v"
ผลลัพธ์ที่ได้อาจคล้ายกับนี้:
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1678886400 10:00:00 elasticsearch green 1 1 0 0 0 0 0 0 - 100.0%
status: green หมายถึง Cluster ของคุณทำงานได้อย่างสมบูรณ์และพร้อมใช้งานครับ
curl -X GET "localhost:9200/_cat/nodes?v"
จะแสดงข้อมูลเกี่ยวกับ Node ใน Cluster ของคุณครับ
ตอนนี้คุณมี Elasticsearch และ Kibana ที่พร้อมใช้งานแล้วครับ ขั้นตอนต่อไปคือการเริ่มจัดเก็บและค้นหาข้อมูลครับ!
การสร้าง Index และการทำ Mapping
ก่อนที่เราจะเริ่มจัดเก็บข้อมูล เราจำเป็นต้องสร้าง Index และกำหนด Mapping ที่เหมาะสม เพื่อให้ Elasticsearch สามารถจัดเก็บและค้นหาข้อมูลได้อย่างถูกต้องและมีประสิทธิภาพครับ
การสร้าง Index
เราสามารถสร้าง Index ได้ง่ายๆ โดยใช้ HTTP PUT request ไปยัง Elasticsearch ครับ
PUT /products
โดยค่าเริ่มต้น Elasticsearch จะสร้าง Index ด้วยการตั้งค่ามาตรฐาน ซึ่งมักจะมี Primary Shard 1 ชิ้น และ Replica Shard 1 ชิ้น (ในเวอร์ชัน 7+)
คุณสามารถกำหนดจำนวน Shard และ Replica ได้เองตอนสร้าง Index ครับ
PUT /products_v2
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
number_of_shards: จำนวน Primary Shard ที่ต้องการ (กระจายข้อมูล)number_of_replicas: จำนวน Replica Shard ต่อ Primary Shard (สำหรับ Fault Tolerance และเพิ่มประสิทธิภาพการค้นหา)
Dynamic Mapping vs. Explicit Mapping
-
Dynamic Mapping:
หากคุณเพิ่ม Document เข้าไปใน Index ที่ยังไม่มี Mapping Elasticsearch จะพยายามเดาประเภทข้อมูลของแต่ละ Field โดยอัตโนมัติและสร้าง Mapping ให้ครับ นี่เป็นคุณสมบัติที่สะดวกสำหรับการเริ่มต้น แต่บางครั้งอาจไม่ตรงกับความต้องการทั้งหมด โดยเฉพาะสำหรับ Field ประเภท
textซึ่งอาจถูก Mapping เป็นtextและkeywordพร้อมกัน (multi-field) หรือ Field วันที่อาจถูกเดาผิดพลาดครับ -
Explicit Mapping:
คือการกำหนด Mapping ด้วยตัวคุณเองอย่างชัดเจน ซึ่งเป็นวิธีที่แนะนำสำหรับการใช้งานจริง เพื่อให้คุณควบคุมการจัดเก็บและการค้นหาข้อมูลได้อย่างแม่นยำครับ คุณสามารถกำหนด Mapping ตอนสร้าง Index หรือเพิ่ม Mapping ให้กับ Index ที่มีอยู่แล้วก็ได้ครับ
PUT /products_v3
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"product_id": { "type": "keyword" },
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"description": { "type": "text" },
"price": { "type": "float" },
"category": { "type": "keyword" },
"brand": { "type": "keyword" },
"stock": { "type": "integer" },
"available": { "type": "boolean" },
"created_at": { "type": "date", "format": "yyyy-MM-dd'T'HH:mm:ssZ || epoch_millis" }
}
}
}
ในตัวอย่างนี้:
product_id,category,brandถูกกำหนดเป็นkeywordซึ่งเหมาะสำหรับการค้นหาแบบตรงตัว (exact match) และการทำ Aggregationnameและdescriptionถูกกำหนดเป็นtextเพื่อรองรับ Full-text Search และnameยังมี sub-field เป็นkeywordเพื่อให้สามารถค้นหาชื่อสินค้าแบบตรงตัวได้ด้วยครับprice,stock,availableมีประเภทข้อมูลที่ชัดเจนcreated_atถูกกำหนดเป็นdateพร้อมระบุ format เพื่อให้ Elasticsearch จัดการกับข้อมูลวันที่ได้อย่างถูกต้อง
ประเภทข้อมูลที่สำคัญในการทำ Mapping
-
text:ใช้สำหรับข้อความยาวๆ ที่ต้องการ Full-text Search เช่น เนื้อหาบทความ, คำอธิบายสินค้า จะถูกทำการ Analysis (แบ่งคำ, เปลี่ยนเป็นตัวพิมพ์เล็ก ฯลฯ) ก่อนจัดเก็บ
-
keyword:ใช้สำหรับข้อความที่ต้องการค้นหาแบบตรงตัว, การจัดเรียง, หรือการทำ Aggregation เช่น ID สินค้า, ชื่อหมวดหมู่, แท็ก จะไม่ถูกทำการ Analysis
-
integer,long,short,byte:สำหรับตัวเลขจำนวนเต็ม
-
float,double,half_float,scaled_float:สำหรับตัวเลขทศนิยม
-
boolean:สำหรับค่า True/False
-
date:สำหรับข้อมูลวันที่และเวลา สามารถกำหนด format ได้
-
object:สำหรับ Field ที่เป็น JSON Object ซ้อนกัน
-
nested:ใช้สำหรับ Array ของ JSON Object ที่แต่ละ Object ต้องคงความสัมพันธ์ของ Field ภายในไว้ (เช่น Array ของแท็กที่มี Field name และ score)
การกำหนด Custom Analyzer สำหรับภาษาไทย
สำหรับภาษาไทย การแบ่งคำ (tokenization) เป็นสิ่งสำคัญมาก เพราะภาษาไทยไม่มีการเว้นวรรคระหว่างคำเหมือนภาษาอังกฤษ หากใช้ Analyzer มาตรฐานของ Elasticsearch อาจทำให้การค้นหาภาษาไทยไม่แม่นยำครับ
เราสามารถใช้ Plugin เช่น Thai Analyzer for Elasticsearch หรือสร้าง Custom Analyzer โดยใช้ ICU Analysis Plugin (ซึ่งมักจะมาพร้อมกับ Elasticsearch อยู่แล้ว) เพื่อจัดการการแบ่งคำภาษาไทยได้ครับ
ตัวอย่างการสร้าง Custom Analyzer สำหรับภาษาไทยโดยใช้ ICU Tokenizer:
PUT /thai_products
{
"settings": {
"analysis": {
"analyzer": {
"thai_analyzer": {
"tokenizer": "icu_tokenizer",
"filter": [
"lowercase",
"icu_folding"
]
}
}
}
},
"mappings": {
"properties": {
"name_th": {
"type": "text",
"analyzer": "thai_analyzer"
},
"description_th": {
"type": "text",
"analyzer": "thai_analyzer"
},
"category_th": { "type": "keyword" }
}
}
}
ในตัวอย่างนี้ icu_tokenizer จะช่วยแบ่งคำภาษาไทยได้อย่างถูกต้อง และ icu_folding จะช่วยให้การค้นหาไม่คำนึงถึงความแตกต่างของวรรณยุกต์หรือสระบางตัว ซึ่งช่วยให้การค้นหามีความยืดหยุ่นมากขึ้นครับ
การลงทุนกับการทำ Mapping และ Analyzer ที่เหมาะสมตั้งแต่เริ่มต้น จะช่วยให้ระบบค้นหาของคุณมีประสิทธิภาพและแม่นยำสูงสุดครับ
การเพิ่ม, อัปเดต, ลบ Document ใน Elasticsearch
หลังจากสร้าง Index และกำหนด Mapping แล้ว ขั้นตอนต่อไปคือการจัดการกับข้อมูล (Documents) ซึ่งคล้ายกับการทำ CRUD (Create, Read, Update, Delete) ในฐานข้อมูลทั่วไปครับ
การเพิ่ม Document (Indexing)
การเพิ่ม Document เข้าไปใน Index เราเรียกว่าการทำ Indexing ครับ คุณสามารถกำหนด ID ของ Document เองได้ หรือจะให้ Elasticsearch สร้างให้โดยอัตโนมัติก็ได้ครับ
เพิ่ม Document พร้อมกำหนด ID
PUT /products_v3/_doc/SKU001
{
"product_id": "SKU001",
"name": "สมาร์ทโฟนรุ่นใหม่ล่าสุด",
"description": "สัมผัสประสบการณ์การใช้งานที่เหนือกว่าด้วยสมาร์ทโฟนรุ่นใหม่ ประสิทธิภาพสูง กล้องคมชัด แบตอึด",
"price": 25990.00,
"category": ["Electronics", "Mobile Phones"],
"brand": "TechCorp",
"stock": 100,
"available": true,
"tags": ["mobile", "smartphone", "android", "flagship"],
"created_at": "2023-10-26T10:30:00Z"
}
PUT /products_v3/_doc/SKU001: หมายถึงการเพิ่ม Document ใน Indexproducts_v3โดยมี ID เป็นSKU001- ถ้า Document ที่มี ID นี้อยู่แล้ว จะเป็นการอัปเดต Document นั้น (Upsert)
เพิ่ม Document โดยให้ Elasticsearch สร้าง ID ให้
POST /products_v3/_doc
{
"product_id": "SKU002",
"name": "หูฟังไร้สายพรีเมียม",
"description": "หูฟังคุณภาพเสียงคมชัด เบสแน่น ใส่สบาย เหมาะสำหรับคนรักดนตรี",
"price": 3990.00,
"category": ["Electronics", "Audio"],
"brand": "SoundWave",
"stock": 50,
"available": true,
"tags": ["headphone", "wireless", "audio", "hifi"],
"created_at": "2023-10-26T11:00:00Z"
}
POST /products_v3/_doc: Elasticsearch จะสร้าง ID ที่ไม่ซ้ำกันให้โดยอัตโนมัติ
การเพิ่ม Document จำนวนมาก (Bulk API)
หากคุณต้องการเพิ่ม, อัปเดต, หรือลบ Document จำนวนมากในครั้งเดียว การใช้ Bulk API จะมีประสิทธิภาพมากกว่าการส่งคำขอทีละครั้งครับ
POST /_bulk
{ "index": { "_index": "products_v3", "_id": "SKU003" } }
{ "product_id": "SKU003", "name": "สมาร์ทวอทช์", "description": "นาฬิกาอัจฉริยะ ติดตามสุขภาพ", "price": 8990.00, "category": ["Electronics", "Wearables"], "brand": "SmartWear", "stock": 200, "available": true, "tags": ["smartwatch", "fitness"], "created_at": "2023-10-26T12:00:00Z" }
{ "create": { "_index": "products_v3", "_id": "SKU004" } }
{ "product_id": "SKU004", "name": "กล้องวงจรปิดอัจฉริยะ", "description": "กล้องวงจรปิดไร้สาย ความคมชัดสูง", "price": 2990.00, "category": ["Smart Home", "Security"], "brand": "HomeGuard", "stock": 80, "available": true, "tags": ["camera", "security", "smart home"], "created_at": "2023-10-26T13:00:00Z" }
{ "update": { "_index": "products_v3", "_id": "SKU001" } }
{ "doc": { "price": 24990.00, "stock": 95 } }
{ "delete": { "_index": "products_v3", "_id": "SKU002" } }
Bulk API มีรูปแบบเป็น “action” ตามด้วย “document” ในแต่ละบรรทัด โดยมีรูปแบบ JSON ที่คั่นด้วย Newline (NDJSON) ครับ
การอัปเดต Document
มีหลายวิธีในการอัปเดต Document:
Partial Update (แนะนำ)
การอัปเดตบาง Field ของ Document โดยใช้ _update API
POST /products_v3/_update/SKU001
{
"doc": {
"price": 24990.00,
"stock": 95
}
}
Elasticsearch จะดึง Document เดิมมา, อัปเดตเฉพาะ Field ที่ระบุ, แล้วจัดเก็บ Document ใหม่กลับเข้าไป ซึ่งมีประสิทธิภาพกว่าการอัปเดตทั้ง Document ครับ
Update with script
คุณสามารถใช้ Script (เช่น Painless Script) เพื่ออัปเดต Document ตามเงื่อนไขที่ซับซ้อนได้
POST /products_v3/_update/SKU001
{
"script": {
"source": "ctx._source.stock += params.quantity",
"lang": "painless",
"params": {
"quantity": -5
}
}
}
ตัวอย่างนี้จะลดจำนวน stock ลง 5 ชิ้นครับ
การลบ Document
การลบ Document ทำได้โดยระบุ ID ของ Document นั้นครับ
DELETE /products_v3/_doc/SKU002
ถ้าต้องการลบ Index ทั้งหมด ก็สามารถทำได้ง่ายๆ ครับ (ระวังการใช้งานคำสั่งนี้!)
DELETE /products_v3
การจัดการข้อมูล (CRUD) ใน Elasticsearch เป็นพื้นฐานสำคัญในการเตรียมข้อมูลให้พร้อมสำหรับการค้นหาและการวิเคราะห์ครับ
หัวใจของการค้นหา: Query DSL ใน Elasticsearch
Query DSL (Domain Specific Language) คือภาษาที่ใช้ในการสร้างคำค้นหาใน Elasticsearch โดยใช้ JSON เป็นรูปแบบหลัก ทำให้สามารถสร้างคำค้นหาที่ซับซ้อนและยืดหยุ่นได้อย่างมากครับ การเข้าใจ Query DSL เป็นกุญแจสำคัญในการดึงพลังของ Elasticsearch มาใช้งานได้อย่างเต็มที่ครับ
เราจะใช้ _search endpoint ในการค้นหาครับ
GET /products_v3/_search
และส่ง JSON Body เข้าไปในคำขอครับ
Match Query: การค้นหาข้อความแบบ Full-text
เป็น Query พื้นฐานที่สุดสำหรับ Full-text Search ครับ จะทำการ Analysis ข้อความที่ค้นหาและ Field ที่ถูกค้นหา เพื่อให้ได้ผลลัพธ์ที่เกี่ยวข้อง
GET /products_v3/_search
{
"query": {
"match": {
"name": "สมาร์ทโฟน"
}
}
}
จะค้นหา Document ที่ Field name มีคำว่า “สมาร์ทโฟน” ครับ
คุณสามารถเพิ่ม operator เป็น AND หรือ OR ได้
GET /products_v3/_search
{
"query": {
"match": {
"description": {
"query": "ประสิทธิภาพสูง แบตอึด",
"operator": "AND"
}
}
}
}
จะค้นหา Document ที่ Field description มีทั้งคำว่า “ประสิทธิภาพสูง” และ “แบตอึด” ครับ
Match Phrase Query: ค้นหาวลีที่ตรงกัน
ใช้เมื่อต้องการค้นหาวลีที่ตรงกันเป๊ะ โดยคำเหล่านั้นต้องปรากฏเรียงกันตามลำดับที่ระบุ
GET /products_v3/_search
{
"query": {
"match_phrase": {
"description": "กล้องคมชัด"
}
}
}
จะค้นหา Document ที่ Field description มีวลี “กล้องคมชัด” เท่านั้นครับ
Term Query: ค้นหาคำที่ตรงกันเป๊ะ
ใช้สำหรับค้นหาค่าที่ตรงกันเป๊ะ (exact match) โดยจะไม่ทำการ Analysis กับคำค้นหา เหมาะสำหรับ Field ประเภท keyword หรือ Field ที่ไม่ต้องการ Full-text Search ครับ
GET /products_v3/_search
{
"query": {
"term": {
"brand": "TechCorp"
}
}
}
จะค้นหา Document ที่ Field brand มีค่าเป็น “TechCorp” ตรงตัวครับ (ระวังการใช้ term กับ text field เพราะอาจไม่ได้ผลลัพธ์ที่คาดหวัง)
Boolean Query (bool): การรวมเงื่อนไขการค้นหา
เป็น Query ที่ทรงพลังที่สุดตัวหนึ่ง ใช้สำหรับรวม Query ย่อยๆ หลายตัวเข้าด้วยกัน โดยมีเงื่อนไขดังนี้:
must: Document ต้องตรงกับ Query นี้ (เพิ่มคะแนนความเกี่ยวข้อง)filter: Document ต้องตรงกับ Query นี้ (ไม่เพิ่มคะแนนความเกี่ยวข้อง, เร็วกว่า)should: Document อาจจะตรงกับ Query นี้ก็ได้ (เพิ่มคะแนนความเกี่ยวข้อง)must_not: Document ต้องไม่ตรงกับ Query นี้ (ไม่เพิ่มคะแนนความเกี่ยวข้อง)
GET /products_v3/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "สมาร์ทโฟน" } }
],
"filter": [
{ "range": { "price": { "lte": 20000 } } },
{ "term": { "available": true } }
],
"should": [
{ "match": { "description": "กล้อง AI" } }
],
"must_not": [
{ "term": { "brand": "SoundWave" } }
]
}
}
}
ตัวอย่างนี้จะค้นหาสมาร์ทโฟนที่มีราคาไม่เกิน 20,000 บาท และสินค้าพร้อมจำหน่าย และไม่เป็นแบรนด์ SoundWave โดยจะให้คะแนนพิเศษหากมีคำว่า “กล้อง AI” ใน description ครับ
Range Query: การค้นหาในช่วงค่า
ใช้สำหรับค้นหา Document ที่ Field มีค่าอยู่ในช่วงที่กำหนด เหมาะสำหรับตัวเลขและวันที่ครับ
GET /products_v3/_search
{
"query": {
"range": {
"price": {
"gte": 10000,
"lte": 30000
}
}
}
}
gte: มากกว่าหรือเท่ากับ (Greater Than or Equal)gt: มากกว่า (Greater Than)lte: น้อยกว่าหรือเท่ากับ (Less Than or Equal)lt: น้อยกว่า (Less Than)
Wildcard และ Regexp Query: การค้นหาด้วยรูปแบบ
ใช้สำหรับการค้นหาคำที่ตรงกับรูปแบบที่กำหนด
-
Wildcard Query:
ใช้
*แทนอักขระหลายตัว และ?แทนอักขระตัวเดียวGET /products_v3/_search { "query": { "wildcard": { "name.keyword": "สมาร์ท*" } } }ค้นหาสินค้าที่ชื่อขึ้นต้นด้วย “สมาร์ท” (ต้องใช้กับ
keywordfield เพื่อหลีกเลี่ยงการ Analysis ครับ) -
Regexp Query:
ใช้ Regular Expression ในการค้นหา (มีประสิทธิภาพต่ำกว่า wildcard)
GET /products_v3/_search { "query": { "regexp": { "tags": ".*phone.*" } } }ค้นหา Document ที่ Field
tagsมีคำว่า “phone” อยู่ในส่วนใดส่วนหนึ่ง
Fuzzy Query: การค้นหาที่ทนต่อความผิดพลาด (Typo)
ช่วยให้การค้นหาประสบความสำเร็จแม้ผู้ใช้จะพิมพ์ผิดเล็กน้อย โดยกำหนดค่า fuzziness เป็นจำนวน edit distance (การเปลี่ยนแปลงอักขระ 1 ตัว เช่น เพิ่ม, ลบ, เปลี่ยน) ที่ยอมรับได้ครับ
GET /products_v3/_search
{
"query": {
"match": {
"name": {
"query": "สมาทโฟน",
"fuzziness": "AUTO"
}
}
}
}
"AUTO" เป็นค่าที่แนะนำ ซึ่ง Elasticsearch จะคำนวณ edit distance ที่เหมาะสมให้โดยอิงจากความยาวของคำครับ
Highlighting: การเน้นคำที่ค้นพบ
เพื่อเพิ่มประสบการณ์ผู้ใช้ที่ดีขึ้น คุณสามารถให้ Elasticsearch เน้นคำที่ค้นพบในผลลัพธ์ได้ครับ
GET /products_v3/_search
{
"query": {
"match": {
"description": "ประสิทธิภาพสูง"
}
},
"highlight": {
"fields": {
"description": {}
},
"pre_tags": ["<em>"],
"post_tags": ["</em>"]
}
}
ผลลัพธ์จะส่ง Field highlight กลับมาพร้อมกับข้อความที่ถูกเน้นด้วยแท็ก เช่น "สัมผัสประสบการณ์การใช้งานที่เหนือกว่าด้วยสมาร์ทโฟนรุ่นใหม่ <em>ประสิทธิภาพสูง</em> กล้องคมชัด แบตอึด" ครับ
Query DSL มีความสามารถอีกมากมายให้สำรวจ แต่ Query ที่กล่าวมาข้างต้นเป็นพื้นฐานสำคัญที่จะช่วยให้คุณสร้างระบบค้นหาที่มีประสิทธิภาพได้แล้วครับ
การจัดอันดับความเกี่ยวข้อง (Relevance Scoring) และ Boost
หนึ่งในความสามารถที่โดดเด่นของ Elasticsearch คือการจัดอันดับผลลัพธ์ตามความเกี่ยวข้องกับคำค้นหา ซึ่งเรียกว่า Relevance Scoring ครับ ผลลัพธ์ที่เกี่ยวข้องมากที่สุดจะปรากฏขึ้นก่อนเสมอ ทำให้ผู้ใช้ได้รับข้อมูลที่ต้องการอย่างรวดเร็ว
Elasticsearch คำนวณคะแนนอย่างไร?
Elasticsearch ใช้โมเดลการคำนวณคะแนนที่ซับซ้อน โดยมีพื้นฐานมาจากอัลกอริทึม BM25 (Best Match 25) ซึ่งพัฒนามาจาก TF-IDF (Term Frequency-Inverse Document Frequency) อีกทีครับ หลักการเบื้องต้นมีดังนี้:
-
Term Frequency (TF):
ยิ่งคำค้นหาปรากฏบ่อยในเอกสารนั้นมากเท่าไหร่ เอกสารนั้นก็ยิ่งมีคะแนนสูงขึ้น
-
Inverse Document Frequency (IDF):
ยิ่งคำค้นหาปรากฏในเอกสารจำนวนน้อยใน Index ทั้งหมดมากเท่าไหร่ เอกสารนั้นก็ยิ่งมีคะแนนสูงขึ้น (คำที่หายากจะมีน้ำหนักมากกว่าคำทั่วไป เช่น “โทรศัพท์” มีน้ำหนักมากกว่า “และ”)
-
Field-Length Norm:
เอกสารที่มี Field สั้นๆ ที่มีคำค้นหา จะมีคะแนนสูงกว่าเอกสารที่มี Field ยาวๆ ที่มีคำเดียวกัน (เพราะคำนั้นมีความสำคัญในบริบทที่สั้นกว่า)
นอกจากนี้ ยังมีปัจจัยอื่นๆ เช่น Boost, Query Clause Weight ที่เข้ามาเกี่ยวข้องในการคำนวณคะแนนด้วยครับ คะแนนที่ได้จะอยู่ใน Field _score ของแต่ละ Document ในผลลัพธ์การค้นหาครับ
การใช้ Boost เพื่อเพิ่มน้ำหนักให้ Field
บางครั้งเราต้องการให้ Field บาง Field มีความสำคัญมากกว่า Field อื่นๆ ในการจัดอันดับ เช่น ชื่อสินค้าควรมีความสำคัญมากกว่าคำอธิบายสินค้า เราสามารถใช้พารามิเตอร์ boost เพื่อเพิ่มน้ำหนักให้กับ Field หรือ Query Clause ได้ครับ
GET /products_v3/_search
{
"query": {
"match": {
"name": {
"query": "สมาร์ทโฟน",
"boost": 2
}
}
}
}
ในตัวอย่างนี้ ถ้าคำว่า “สมาร์ทโฟน” ปรากฏใน Field name จะได้รับคะแนนเป็นสองเท่า เมื่อเทียบกับการปรากฏใน Field อื่นๆ ที่ไม่มีการกำหนด Boost ครับ
คุณสามารถใช้ boost ร่วมกับ Boolean Query ได้ด้วย:
GET /products_v3/_search
{
"query": {
"bool": {
"should": [
{ "match": { "name": { "query": "สมาร์ทโฟน", "boost": 3 } } },
{ "match": { "description": { "query": "สมาร์ทโฟน", "boost": 1 } } },
{ "match": { "tags": { "query": "flagship", "boost": 2 } } }
]
}
}
}
Query นี้จะให้คะแนนความสำคัญกับ name มากที่สุด, รองลงมาคือ tags และ description ตามลำดับครับ
Function Score Query: การปรับคะแนนอย่างละเอียด
สำหรับกรณีที่ต้องการปรับคะแนนความเกี่ยวข้องที่ซับซ้อนมากขึ้น เช่น ต้องการให้สินค้าใหม่ๆ มีคะแนนสูงขึ้น, สินค้าที่มีสต็อกเยอะมีคะแนนสูงขึ้น, หรือสินค้าที่มีรีวิวดีมีคะแนนสูงขึ้น เราสามารถใช้ function_score query ได้ครับ
GET /products_v3/_search
{
"query": {
"function_score": {
"query": {
"match": { "name": "สมาร์ทโฟน" }
},
"functions": [
{
"field_value_factor": {
"field": "stock",
"modifier": "log1p",
"factor": 0.5
}
},
{
"gauss": {
"created_at": {
"origin": "now",
"scale": "7d",
"offset": "0d",
"decay": 0.5
}
}
}
],
"boost_mode": "multiply"
}
}
}
ในตัวอย่างนี้:
field_value_factorจะเพิ่มคะแนนตามจำนวนstock(ยิ่งมีสต็อกเยอะยิ่งได้คะแนนเยอะ)gauss(Gaussian decay function) จะให้คะแนนสูงขึ้นสำหรับสินค้าที่created_atใกล้กับเวลาปัจจุบัน (สินค้าใหม่) โดยคะแนนจะลดลงเมื่อเวลาผ่านไปboost_mode: "multiply"จะนำคะแนนจาก Function ต่างๆ มาคูณกับคะแนนเริ่มต้น
การปรับแต่ง Relevance Scoring อย่างละเอียดเป็นสิ่งสำคัญในการสร้างระบบค้นหาที่ “อัจฉริยะ” จริงๆ เพราะจะทำให้ผู้ใช้ได้รับผลลัพธ์ที่ตรงใจและเป็นประโยชน์สูงสุดครับ
Aggregations: การวิเคราะห์ข้อมูลเชิงลึกและ Faceted Search
นอกจากการค้นหาแล้ว Elasticsearch ยังมีความสามารถในการทำ Aggregations ซึ่งเป็นเครื่องมือที่ทรงพลังสำหรับการวิเคราะห์ข้อมูลและสร้างรายงานสรุปได้แบบเรียลไทม์ Aggregations คล้ายกับคำสั่ง GROUP BY ใน SQL แต่มีความยืดหยุ่นและประสิทธิภาพสูงกว่ามากครับ
Aggregations มักใช้ในการสร้าง Faceted Search (ตัวกรองสินค้าตามหมวดหมู่, ช่วงราคา, แบรนด์), Dashboard สำหรับ Business Intelligence, หรือการวิเคราะห์ Log ครับ