Sử dụng aggregation pipeline với $group và $match lồng $all + $elemMatch để tìm nhóm tài liệu chia sẻ cùng một giá trị trường VÀ chứa tất cả các giá trị chỉ định của trường khác.
Tạo collection:
> db.demo393.insertOne({Id1:"1", Name:"Chris", Id2:"100"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e6dd522064be7ab44e804") }
> db.demo393.insertOne({Id1:"1", Name:"Chris", Id2:"101"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e6dd522064be7ab44e805") }
> db.demo393.insertOne({Id1:"3", Name:"Chris", Id2:"100"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e6dd522064be7ab44e806") }
> db.demo393.insertOne({Id1:"3", Name:"Mike", Id2:"101"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e6dd522064be7ab44e807") }
Xem dữ liệu:
> db.demo393.find();
Aggregation: nhóm theo Id1, chỉ giữ nhóm có Name="Chris" VÀ chứa CẢ HAI Id2="100" VÀ Id2="101":
> db.demo393.aggregate([ { "$match": { "Name": "Chris" } }, { "$group": { "_id": "$Id1", "docs": { "$push": "$$ROOT" }, "count": { "$sum": 1 } }}, { "$match": { "count": { "$gt": 1 }, "docs": { "$all": [ { "$elemMatch": { "Id2": "100" } }, { "$elemMatch": { "Id2": "101" } } ] } }} ])Kết quả (chỉ nhóm Id1="1" thỏa mãn):
Phân tích logic:
$matchName="Chris": lọc trước$groupby Id1: gom tài liệu, đẩy toàn bộ doc vào mảngdocs, đếmcount$matchthứ 2: lọc nhóm có count>1 VÀ mảngdocschứa **tất cả** các phần tử khớp 2 điều kiện Id2=100 và Id2=101 (qua$all+$elemMatch)Kỹ thuật này tìm "giao nhau" các tập tài liệu theo nhiều tiêu chí.