Theo nghĩa đơn giản nhất, điều này chỉ tuân theo dạng cơ bản của "ký hiệu dấu chấm" như được sử dụng bởi MongoDB. Điều đó sẽ hoạt động bất kể thành viên mảng bên trong nằm trong thành viên mảng nào, miễn là nó khớp với một giá trị:
db.mycollection.find({
"someArray.someNestedArray.name": "value"
})
Điều đó tốt cho một giá trị "trường đơn", để khớp với nhiều trường, bạn sẽ sử dụng $elemMatch
:
db.mycollection.find({
"someArray": {
"$elemMatch": {
"name": "name1",
"someNestedArray": {
"$elemMatch": {
"name": "value",
"otherField": 1
}
}
}
}
})
Điều đó khớp với tài liệu sẽ chứa một cái gì đó với một trường tại "đường dẫn" đó khớp với giá trị. Nếu bạn định "đối sánh và lọc" kết quả để chỉ phần tử phù hợp được trả về, thì điều này không thể thực hiện được với phép chiếu toán tử vị trí, như đã trích dẫn:
Mảng lồng nhau
Toán tử vị trí $ không thể được sử dụng cho các truy vấn đi qua nhiều hơn một mảng, chẳng hạn như truy vấn đi qua các mảng được lồng trong các mảng khác, bởi vì sự thay thế cho $ placeholder là một giá trị duy nhất
MongoDB hiện đại
Chúng tôi có thể làm điều này bằng cách áp dụng $filter
và $map
đây. $map
thực sự cần thiết vì mảng "bên trong" có thể thay đổi do kết quả của quá trình "lọc", và mảng "bên ngoài" tất nhiên không phù hợp với các điều kiện khi "bên trong" bị loại bỏ tất cả các phần tử.
Một lần nữa làm theo ví dụ về việc thực sự có nhiều thuộc tính để khớp trong mỗi mảng:
db.mycollection.aggregate([
{ "$match": {
"someArray": {
"$elemMatch": {
"name": "name1",
"someNestedArray": {
"$elemMatch": {
"name": "value",
"otherField": 1
}
}
}
}
}},
{ "$addFields": {
"someArray": {
"$filter": {
"input": {
"$map": {
"input": "$someArray",
"as": "sa",
"in": {
"name": "$$sa.name",
"someNestedArray": {
"$filter": {
"input": "$$sa.someNestedArray",
"as": "sn",
"cond": {
"$and": [
{ "$eq": [ "$$sn.name", "value" ] },
{ "$eq": [ "$$sn.otherField", 1 ] }
]
}
}
}
}
},
},
"as": "sa",
"cond": {
"$and": [
{ "$eq": [ "$$sa.name", "name1" ] },
{ "$gt": [ { "$size": "$$sa.someNestedArray" }, 0 ] }
]
}
}
}
}}
])
Do đó, trên mảng "bên ngoài", $filter
thực sự nhìn vào $size
của mảng "bên trong" sau khi chính nó được "lọc", vì vậy bạn có thể từ chối các kết quả đó khi toàn bộ mảng bên trong thực tế khớp với ghi chú.
MongoDB cũ hơn
Để chỉ "chiếu" phần tử phù hợp, bạn cần .aggregate()
phương pháp:
db.mycollection.aggregate([
// Match possible documents
{ "$match": {
"someArray.someNestedArray.name": "value"
}},
// Unwind each array
{ "$unwind": "$someArray" },
{ "$unwind": "$someArray.someNestedArray" },
// Filter just the matching elements
{ "$match": {
"someArray.someNestedArray.name": "value"
}},
// Group to inner array
{ "$group": {
"_id": {
"_id": "$_id",
"name": "$someArray.name"
},
"someKey": { "$first": "$someKey" },
"someNestedArray": { "$push": "$someArray.someNestedArray" }
}},
// Group to outer array
{ "$group": {
"_id": "$_id._id",
"someKey": { "$first": "$someKey" },
"someArray": { "$push": {
"name": "$_id.name",
"someNestedArray": "$someNestedArray"
}}
}}
])
Điều đó cho phép bạn "lọc" các kết quả phù hợp trong các mảng lồng nhau cho một hoặc nhiều kết quả trong tài liệu.