Mongoid (Map/Reduce & Aggregations)


โดย แสงเดือน จันทร์ใหม่ – 1 มิถุนายน 2558

Mongoid Map/Reduce และ Mongoid Aggregations ถือเป็นหนึ่งในการ Query ข้อมูลของ Mongoid โดยสามารถอธิบายการทำงานได้ดังนี้

Mongoid Map/Reduce

Map/Reduce ถือเป็นการ join ข้อมูลจากตารางข้อมูลในฐานข้อมูล แต่มีความยืดหยุ่นและการดำเนินการที่หลากหลายกว่า

Map เป็นการ join ข้อมูลในฐานข้อมูลจากหลายๆ ตารางที่เก็บแยกกัน ให้กลายเป็นหนึ่งตารางที่มีปริมาณข้อมูลในแต่ละ record ประกอบด้วย field ข้อมูลจำนวนมากขึ้น ที่มีความสัมพันธ์กัน

Reduce เป็นการนำผลลัพธ์จากการ Map มาคัดกรองให้เกิดเป็นผลลัพธ์ที่ตรงตามความต้องการมากขึ้น ทั้งนี้การ Reduce ของ Mongoid สามารถทำได้หลากหลายวิธี รวมทั้งการ Aggregate ด้วย

Mongoid Map/Reduce มีพื้นฐานมาจาก Mongo Map/Reduce คือประกอบด้วยฟังก์ชั่น 2 ฟังก์ชั่น คือ map และ reduce แต่ใน Mongoid มีการปรับการจัดการในการเรียกใช้งานให้สะดวกขึ้น เช่น คำสั่ง .out เพื่อสามารถเลือกรูปแบบการจัดเก็บผลลัพธ์ได้ เป็นต้น

ตัวอย่างการใช้งาน Mongoid Map/Reduce

map = %Q{
  function() {
    emit(this.name, { likes: this.likes });
  }
}

reduce = %Q{
  function(key, values) {
    var result = { likes: 0 };
    values.forEach(function(value) {
      result.likes += value.likes;
    });
    return result;
  }
}

Band.where(:likes.gt => 100).map_reduce(map, reduce).out(inline: true)

จากตัวอย่างเป็นการเรียกใช้งาน Map/Reduce ผ่าน Criteria คือเอาเฉพาะ record ที่มีค่า likes มากกว่า 100 มาทำการ Map และ Reduce 
โดยในกรณีตัวอย่างข้างต้นนี้ผลลัพธ์ที่ถูก return กลับมา คือ ค่าผลรวมของ field like ใน Criteria

Mongoid Aggregations

Aggregations เป็นการรวมรวบข้อมูลเพื่อทำให้เกิดเป็นผลลัพธ์ใดๆ ที่ใช้ประโยชน์ได้และตรงตามความต้องการ

Mongoid Aggregations ประกอบด้วยการดำเนินการเพื่อให้ได้มาซึ่งผลลัพธ์ ดังนี้

  1. #avg ใช้สำหรับหาค่าเฉลี่ย
  2. #max ใช้สำหรับหาค่าที่มากที่สุด
  3. #min ใช้สำหรับหาค่าที่น้อยที่สุด
  4. #sum ใช้สำหรับหาค่าผลรวม

โดยการดำเนินการเหล่านี้สามารถเรียกใช้งานได้ผ่าน Class หรือ Criteria ตัวอย่าง เช่น

  • การเรียกใช้งานผ่าน Class

          Band.max(:likes)

เป็นการหาค่าที่มากที่สุดของ  field likes ใน model Band

  • การเรียกใช้งานผ่าน Criteria

          Band.where(:likes.gt => 100).avg(:likes)

เป็นการหาค่าเฉลี่ยของ field likes ที่มีค่ามากกว่า 100 ใน model Band