การสร้าง Custom Analyzer ของ Elasticsearch

เราได้พูดถึงผลลัพธ์ที่ได้จากการเลือกใช้งาน Elasticsearch Analyzer กันแล้วในบทความที่แล้ว ซึ่งทางทีมพัฒนาของ Elasticsearch ก็ได้สร้าง Analyzer มาให้เราได้เลือกใช้มากมายเลยทีเดียว หรือถ้าเกิด Analyzer ที่เตรียมไว้ให้ยังไม่โดนใจ Elasticsearch ก็ยังมีความยืดหยุ่นมากพอให้เราสามารถสร้าง Analyzer ขึ้นมาใช้เองได้บทความนี้เราจะมาพูดถึงโครงสร้างและวิธีการสร้าง Analyzer ขึ้นมาใช้เองกัน

ก่อนที่เราจะสร้าง Analyzer ได้ เราก็ต้องรู้ก่อนว่าเจ้า Analyzer นั้นมีส่วนประกอบอะไรบ้าง

Character Filters
ทำหน้าที่จัดการเกี่ยวกับอักขระที่ถูกส่งเข้ามาคือมองถึงระดับตัวอักขระเลยนะ ไม่ว่าจะเป็นเพิ่ม ลบหรือเปลี่ยนค่าไปเลยก็ได้ เช่น เปลี่ยนจากตัวเลขไทยให้เป็นตัวเลขอารบิก เป็นต้น Analyzer อาจจะไม่มี character filter เลย หรืออาจจะมีหลาย character filter ก็ได้ ซึ่งจะถูกใช้งานตามลำดับที่ตั้งค่าไว้ สำหรับตอนนี้ Elasticsearch 7.2 ก็จะมี html_strip, mapping และ pattern_replace ไว้ให้ใช้ครับ

Tokenizer
ทำหน้าที่สร้าง tokens จากอักขระทั้งหมดที่ถูกส่งเข้ามา (input) หรือพูดให้เข้าใจง่ายๆ ก็คือ แยกเป็นคำๆ นั้นเอง เช่น

"อ่านบทความที่ imooh.com" 

ก็อาจจะกลายเป็น

["อ่าน", "บท", "ความ", "imooh", "com"] 

tokenizer จะเป็นตัวที่บอกให้ Elasticsearch รู้เกี่ยวกับลำดับหรือตำแหน่งของแต่ละคำ รวมถึงตำแหน่งของอักขระตัวแรกและตัวสุดท้ายของคำที่อยู่ใน input ที่ถูกส่งเข้ามา Analyzer ประกอบด้วย Tokenizer เพียง 1 tokenizer เท่านั้น ที่ผมใช้อยู่บ่อยๆ ก็จะมี thai, keyword, whitespace, standard และ uax_url_email ครับ

Token Filters
หน้าที่คล้ายๆ กับ Character Filter แต่จะถูกใช้กับ token หรือคำ เช่น lowercase ก็จะเป็นให้เป็นตัวพิมพ์เล็ก stop ก็จะลบคำที่เป็น stop words ออก สำหรับ Analyzer อาจจะมี token filter มากกว่าหนึ่งหรือไม่มีเลยก็ได้ครับ

ลองสร้าง Custom Analyzer สำหรับเปลี่ยนตัวเลขไทยให้เป็นตัวเลขอารบิก เช่น วันที่ ๑๒ กรกฎาคม ๒๕๖๒ เป็น วันที่ 12 กรกฎาคม 2562

PUT test_custom_analyzer
{
  "settings": {
    "analysis": {
      "char_filter": {
        "convert_thai_number": {
          "type": "mapping",
          "mappings": [
            "๐ => 0",
            "๑ => 1",
            "๒ => 2",
            "๓ => 3",
            "๔ => 4",
            "๕ => 5",
            "๖ => 6",
            "๗ => 7",
            "๘ => 8",
            "๙ => 9"
          ]
        }
      },
      "analyzer": {
        "my_number": {
          "type": "custom",
          "char_filter": ["convert_thai_number"],
          "tokenizer": "thai"
        }
      }
    }
  }
}

จากนั้นทดสอบ Analyzer ที่สร้างด้วย analyze API

GET test_custom_analyzer/_analyze
{
  "analyzer": "my_number",
  "text": ["๐๑๒๓๔๕๖๗๘๙"]
}

ผลลัพธ์ที่ได้ควรเป็นประมาณนี้นะครับ

{
  "tokens": [
    {
      "token": "0123456789",
      "start_offset": 0,
      "end_offset": 10,
      "type": "word",
      "position": 0
    }
  ]
}

แหล่งข้อมูล: Anatomy of Elasticsearch analyzer