W najprostszym sensie jest to po prostu podstawowa forma „notacji kropkowej” używana przez MongoDB. To zadziała niezależnie od tego, w którym członie tablicy znajduje się wewnętrzny element tablicy, o ile pasuje do wartości:
db.mycollection.find({
"someArray.someNestedArray.name": "value"
})
To jest w porządku dla wartości "pojedynczego pola", do dopasowania wielu pól użyjesz $elemMatch
:
db.mycollection.find({
"someArray": {
"$elemMatch": {
"name": "name1",
"someNestedArray": {
"$elemMatch": {
"name": "value",
"otherField": 1
}
}
}
}
})
To pasuje do dokumentu, który zawierałby coś z polem w tej "ścieżce" pasującym do wartości. Jeśli zamierzasz „dopasować i przefiltrować” wynik tak, aby zwracany był tylko dopasowany element, nie jest to możliwe w przypadku projekcji operatora pozycyjnego, jak cytuję:
Zagnieżdżone tablice
Pozycyjnego operatora $ nie można używać w zapytaniach, które przechodzą przez więcej niż jedną tablicę, takich jak zapytania, które przechodzą przez tablice zagnieżdżone w innych tablicach, ponieważ zamiennik symbolu zastępczego $ jest pojedynczą wartością
Nowoczesne MongoDB
Możemy to zrobić, stosując $filter
i $map
tutaj. $map
jest naprawdę potrzebne, ponieważ tablica „wewnętrzna” może się zmienić w wyniku „filtrowania”, a tablica „zewnętrzna” oczywiście nie pasuje do warunków, gdy „wewnętrzna” została pozbawiona wszystkich elementów.
Ponownie podążając za przykładem posiadania wielu właściwości do dopasowania w każdej tablicy:
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 ] }
]
}
}
}
}}
])
Dlatego w tablicy „zewnętrznej” $filter
faktycznie patrzy na $size
tablicy „wewnętrznej” po jej „odfiltrowaniu”, więc możesz odrzucić te wyniki, gdy cała tablica wewnętrzna faktycznie pasuje do notatek.
Starsza baza danych MongoDB
Aby "zaprojektować" tylko dopasowany element, potrzebujesz .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"
}}
}}
])
Pozwala to na „filtrowanie” dopasowań w zagnieżdżonych tablicach pod kątem jednego lub więcej wyników w dokumencie.