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

Sử dụng mảng làm bộ lọc truy vấn subdocument trong MongoDB

Để lọc các phần tử trong mảng subdocument dựa trên việc **trường của phần tử có nằm trong một mảng giá trị cho trước không**, MongoDB cung cấp toán tử $setIsSubset trong Aggregation Pipeline. Toán tử này trả về true nếu tập hợp đầu tiên là tập con của tập hợp thứ hai.

1. Tạo bộ sưu tập và chèn dữ liệu

> db.demo407.insertOne({
    Name: "Chris",
    "details": [
        { id: 100 },
        { id: 110 },
        { id: 130 }
    ]
});
{ "acknowledged": true, "insertedId": ObjectId("5e70dffe15dc524f70227677") }

2. Xem dữ liệu

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

Kết quả:

{ "_id": ObjectId("..."), "Name": "Chris", "details": [ { "id": 100 }, { "id": 110 }, { "id": 130 } ] }

3. Lọc chỉ giữ phần tử có id IN [100, 130]

> db.demo407.aggregate([
    { $match: {} },
    {
        $project: {
            "details": {
                $filter: {
                    input: "$details",
                    as: "output",
                    cond: { $setIsSubset: [ ["$$output.id"], [100, 130] ] }
                }
            }
        }
    }
]);

4. Kết quả

{ "_id": ObjectId("..."), "details": [ { "id": 100 }, { "id": 130 } ] }

Giải thích:

  • $filter: Duyệt mảng details, giữ phần tử thỏa cond.
  • $$output.id: Trường id của phần tử hiện tại (bọc trong mảng ["$$output.id"] để thành set).
  • $setIsSubset: [ [A], [B] ]: Trả về true nếu A ⊆ B. Ở đây kiểm tra {id} ⊆ {100,130}.

Cách thay thế đơn giản hơn (MongoDB 3.6+): Dùng $in trong $filter:

cond: { $in: ["$$output.id", [100, 130]] }

Cách này dễ đọc hơn và hiệu suất tương đương.