Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Tìm document MongoDB lồng 2 cấp với $where

Tìm kiếm sâu 2 cấp độ với $where (JavaScript)

$where cho phép chạy JavaScript tùy ý để tìm document. Dùng khi cấu trúc lồng không cố định hoặc phức tạp.

1. Dữ liệu: Object lồng 2 cấp (FirstPosition, SecondPosition)

> db.demo468.insertOne({
    _id: new ObjectId(),
    FirstPosition: { StudentName: "Chris", StudentAge: 23 },
    SecondPosition: { StudentName: "David", StudentAge: 20 }
});
> db.demo468.insertOne({
    _id: new ObjectId(),
    FirstPosition: { StudentName: "Carol", StudentAge: 21 },
    SecondPosition: { StudentName: "John", StudentAge: 22 }
});

2. Tìm document có StudentName = "John" ở bất kỳ cấp nào

> db.demo468.find({
    $where: function() {
        for (var key in this) {
            if (this[key] && this[key]["StudentName"] == "John") {
                return true;
            }
        }
        return false;
    }
});

3. Kết quả

{ 
    "_id": ObjectId("5e804fb0b0f3fa88e227906a"),
    "FirstPosition": { "StudentName": "Carol", "StudentAge": 21 },
    "SecondPosition": { "StudentName": "John", "StudentAge": 22 }
}

⚠️ Cảnh báo quan trọng về $where

Vấn đềMô tả
🚫 Không dùng indexQuét toàn bộ collection (COLLSCAN)
🚫 Chạy JavaScript engineChậm hơn operator gốc hàng chục lần
🚫 Rủi ro injectionNếu input từ user không sanitize
🚫 Không hoạt động sharded clusterGiới hạn môi trường production

Giải pháp thay thế TỐT HƠN

Cách 1: $or với dot notation (nếu biết tên trường)

db.demo468.find({
    $or: [
        { "FirstPosition.StudentName": "John" },
        { "SecondPosition.StudentName": "John" }
    ]
});

Cách 2: Schema design tốt hơn - flatten mảng

// Thay vì object lồng, dùng mảng positions
{
    positions: [
        { type: "FirstPosition", StudentName: "Chris", StudentAge: 23 },
        { type: "SecondPosition", StudentName: "David", StudentAge: 20 }
    ]
}

// Truy vấn đơn giản, dùng index
db.collection.find({ "positions.StudentName": "John" });

Cách 3: $expr + $objectToArray (MongoDB 3.6+)

db.demo468.find({
    $expr: {
        $in: [
            "John",
            { $map: {
                input: { $objectToArray: "$$ROOT" },
                as: "field",
                in: "$$field.v.StudentName"
            }}
        ]
    }
});

Tóm lại: Chỉ dùng $where khi bất khả kháng. Luôn ưu tiên redesign schema hoặc dùng operator gốc.