Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

วิธีค้นหาเอกสารด้วย Tags ใน MongoDB

การค้นหาเอกสารด้วย Tags (Array Field) ใน MongoDB

ใช้ ออเปอเรเตอร์ $elemMatch หรือ Query โดยตรงบน Array Field เพื่อค้นหาเอกสารที่มี Tag ที่ต้องการ

ตัวอย่างการสร้างคอลเลกชันและเพิ่มข้อมูล

> db.getDocumentsByTagsDemo.insertOne({"Tags":["Tag-1", "Tag-2", "Tag-3"]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d5d628fa4220163b79") }
> db.getDocumentsByTagsDemo.insertOne({"Tags":["Tag-2", "Tag-4", "Tag-5"]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d5d628fa4220163b7a") }
> db.getDocumentsByTagsDemo.insertOne({"Tags":["Tag-6", "Tag-4", "Tag-3"]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d6d628fa4220163b7b") }

แสดงข้อมูลทั้งหมด

> db.getDocumentsByTagsDemo.find().pretty();

ผลลัพธ์:

{ "_id" : ObjectId("5c9eb4d5d628fa4220163b79"), "Tags" : [ "Tag-1", "Tag-2", "Tag-3" ] }
{ "_id" : ObjectId("5c9eb4d5d628fa4220163b7a"), "Tags" : [ "Tag-2", "Tag-4", "Tag-5" ] }
{ "_id" : ObjectId("5c9eb4d6d628fa4220163b7b"), "Tags" : [ "Tag-6", "Tag-4", "Tag-3" ] }

วิธีที่ 1: ใช้ $elemMatch (สำหรับ Array of Objects หรือเงื่อนไขซับซ้อน)

> db.getDocumentsByTagsDemo.find({Tags: { $elemMatch: { $eq: "Tag-2" } }}).pretty();

ผลลัพธ์ (มี Tag-2):

{ "_id" : ObjectId("5c9eb4d5d628fa4220163b79"), "Tags" : [ "Tag-1", "Tag-2", "Tag-3" ] }
{ "_id" : ObjectId("5c9eb4d5d628fa4220163b7a"), "Tags" : [ "Tag-2", "Tag-4", "Tag-5" ] }

วิธีที่ 2: Query โดยตรงบน Array (Simple Equality) - แนะนำสำหรับ Simple Tags

> db.getDocumentsByTagsDemo.find({Tags: "Tag-5"}).pretty();

ผลลัพธ์ (มี Tag-5):

{ "_id" : ObjectId("5c9eb4d5d628fa4220163b7a"), "Tags" : [ "Tag-2", "Tag-4", "Tag-5" ] }

ความแตกต่าง $elemMatch vs Direct Query

คุณสมบัติDirect Query {Tags: "Tag-2"}$elemMatch {$elemMatch: {$eq: "Tag-2"}}
Simple Array (Strings)✅ ทำงานได้ดี เร็วกว่า✅ ทำงานได้ แต่ Overhead มากกว่า
Array of Objects❌ ไม่ได้ (Match ทั้ง Object)✅ จำเป็นต้องใช้
Multiple Conditions on Same Element❌ Match แยก Element ได้✅ Match ใน Element เดียวกัน
Performanceดีกว่า (Simple Index Scan)ช้ากว่า (Complex Matching)

ตัวอย่าง Array of Objects (ต้องใช้ $elemMatch)

> db.products.insertOne({
    name: "Laptop",
    specs: [
        { name: "RAM", value: "16GB" },
        { name: "CPU", value: "i7" }
    ]
});

> db.products.insertOne({
    name: "Phone",
    specs: [
        { name: "RAM", value: "8GB" },
        { name: "CPU", value: "Snapdragon" }
    ]
});

// ❌ ผิด: จะ match ทั้ง RAM=16GB และ CPU=i7 ใน Document เดียวกัน (ไม่มี)
db.products.find({ "specs.name": "RAM", "specs.value": "8GB" });

// ✅ ถูก: ใช้ $elemMatch - match ใน Element เดียวกัน
db.products.find({ 
    specs: { $elemMatch: { name: "RAM", value: "8GB" } } 
});

Query Tags แบบหลายเงื่อนไข

// มี Tag-2 AND Tag-3 (ทั้งคู่)
db.getDocumentsByTagsDemo.find({ Tags: { $all: ["Tag-2", "Tag-3"] } });

// มี Tag-2 OR Tag-5 (อย่างน้อย 1 ตัว)
db.getDocumentsByTagsDemo.find({ Tags: { $in: ["Tag-2", "Tag-5"] } });

// มี Tag-2 แต่ไม่มี Tag-4
db.getDocumentsByTagsDemo.find({ Tags: "Tag-2", Tags: { $ne: "Tag-4" } });
// หรือ
db.getDocumentsByTagsDemo.find({ 
    $and: [ { Tags: "Tag-2" }, { Tags: { $nin: ["Tag-4"] } } ] 
});

Index สำหรับ Tags Array

// Single Field Index บน Array -> Multikey Index อัตโนมัติ
db.getDocumentsByTagsDemo.createIndex({ "Tags": 1 });

// Compound Index
db.getDocumentsByTagsDemo.createIndex({ "Tags": 1, "createdAt": -1 });

Aggregation สำหรับ Tag Analytics

// นับจำนวนเอกสารต่อ Tag
db.getDocumentsByTagsDemo.aggregate([
    { $unwind: "$Tags" },
    { $group: { _id: "$Tags", count: { $sum: 1 } } },
    { $sort: { count: -1 } }
]);

// Top 5 Tags
db.getDocumentsByTagsDemo.aggregate([
    { $unwind: "$Tags" },
    { $group: { _id: "$Tags", count: { $sum: 1 } } },
    { $sort: { count: -1 } },
    { $limit: 5 }
]);

สรุปคำแนะนำ

  • Simple String Tags: ใช้ Direct Query { tags: "value" } เร็วที่สุด
  • Array of Objects: ต้องใช้ $elemMatch
  • Multiple Tags (AND): ใช้ $all
  • Multiple Tags (OR): ใช้ $in
  • Index: สร้าง Index บน Tags Field (Multikey Index อัตโนมัติ)