V nejjednodušším smyslu to jen následuje základní formu „tečkové notace“, kterou používá MongoDB. To bude fungovat bez ohledu na to, ve kterém členu pole je člen vnitřního pole, pokud odpovídá hodnotě:
db.mycollection.find({
"someArray.someNestedArray.name": "value"
})
To je v pořádku pro hodnotu "jednoho pole", pro shodu více polí byste použili $elemMatch
:
db.mycollection.find({
"someArray": {
"$elemMatch": {
"name": "name1",
"someNestedArray": {
"$elemMatch": {
"name": "value",
"otherField": 1
}
}
}
}
})
To odpovídá dokumentu, který by obsahoval něco s polem na této "cestě" odpovídající hodnotě. Pokud jste zamýšleli „porovnat a filtrovat“ výsledek tak, aby byl vrácen pouze odpovídající prvek, není to možné s projekcí pozičního operátora, jak je uvedeno:
Vnořená pole
Poziční operátor $ nelze použít pro dotazy, které procházejí více než jedním polem, jako jsou dotazy, které procházejí pole vnořená do jiných polí, protože zástupný symbol $ je nahrazen jedinou hodnotou
Moderní MongoDB
Můžeme to udělat použitím $filter
a $map
tady. $map
je skutečně potřeba, protože „vnitřní“ pole se může změnit v důsledku „filtrování“ a „vnější“ pole samozřejmě neodpovídá podmínkám, kdy bylo „vnitřní“ zbaveno všech prvků.
Opět následuje příklad skutečného použití více vlastností pro shodu v každém poli:
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 ] }
]
}
}
}
}}
])
Proto na "vnějším" poli $filter
ve skutečnosti se dívá na $size
"vnitřního" pole poté, co bylo "filtrováno", takže tyto výsledky můžete odmítnout, když celé vnitřní pole ve skutečnosti odpovídá poznámce.
Starší MongoDB
Abyste mohli „promítnout“ pouze odpovídající prvek, potřebujete .aggregate()
metoda:
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"
}}
}}
])
To vám umožňuje "filtrovat" shody ve vnořených polích pro jeden nebo více výsledků v dokumentu.