Załóżmy, że masz w mojej kolekcji następujące dokumenty:
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":"circle",
"color":"green"
}
]
}
Wykonaj zapytanie:
db.test.find({"shapes.color": "red"}, {"shapes.color": 1})
Lub
db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})
Zwraca dopasowany dokument (Dokument 1) , ale zawsze ze WSZYSTKIMMI elementami tablicy w shapes
:
{ "shapes":
[
{"shape": "square", "color": "blue"},
{"shape": "circle", "color": "red"}
]
}
Chciałbym jednak uzyskać dokument (Dokument 1) tylko z tablicą zawierającą color=red
:
{ "shapes":
[
{"shape": "circle", "color": "red"}
]
}
W jaki sposób mogę to zrobić?
aggregate
.db.test.find({}, {shapes: {$elemMatch: {color: "red"}}});
Nowa struktura agregacji w MongoDB 2.2+ stanowi alternatywę dla Map / Reduce. Za pomocą
$unwind
operatora można podzielićshapes
tablicę na strumień dokumentów, które można dopasować:Prowadzi do:
źródło
$elemMatch
jest inna opcja. Dostałem się tutaj przez pytanie z Google Group, w którym $ elemMatch nie działałoby, ponieważ zwraca tylko pierwsze dopasowanie dla dokumentu.{ $project : { shapes : 1 } }
- co wydawało się działać i byłoby pomocne, gdyby załączone dokumenty były duże, a chciałeś tylko zobaczyćshapes
kluczowe wartości.Innym interesującym sposobem jest użycie $ redact , która jest jedną z nowych funkcji agregujących MongoDB 2.6 . Jeśli używasz wersji 2.6, nie potrzebujesz $ odprężenia, co może powodować problemy z wydajnością, jeśli masz duże tablice.
$redact
„ogranicza zawartość dokumentów na podstawie informacji przechowywanych w samych dokumentach” . Będzie więc działał tylko w dokumencie . Zasadniczo skanuje dokument od góry do dołu i sprawdza, czy pasuje doif
stanu, w którym się znajduje$cond
, jeśli jest zgodny, zachowa zawartość ($$DESCEND
) lub usunie ($$PRUNE
).W powyższym przykładzie najpierw
$match
zwraca całąshapes
tablicę, a $ redact usuwa ją do oczekiwanego wyniku.Zauważ, że
{$not:"$color"}
jest to konieczne, ponieważ skanuje również najwyższy dokument, a jeśli$redact
nie znajdziecolor
pola na najwyższym poziomie, to zwróci to,false
co może pozbawić cały dokument, którego nie chcemy.źródło
$match
Parametr wyboru pola jest ograniczony do pełnych właściwości. Nie można go użyć do wybrania części tablicy, tylko całej tablicy. Próbowałem użyć operatora $ pozycyjnego , ale to nie działało.
Najłatwiej jest po prostu filtrować kształty w kliencie .
Jeśli naprawdę potrzebujesz poprawnych danych wyjściowych bezpośrednio z MongoDB, możesz użyć mapowania do filtrowania kształtów.
źródło
Lepiej możesz zapytać w dopasowanym elemencie tablicy,
$slice
czy przydatne jest zwrócenie znaczącego obiektu w tablicy.$slice
jest przydatny, gdy znasz indeks elementu, ale czasami chcesz, który element tablicy spełni twoje kryteria. Możesz zwrócić pasujący element za pomocą$
operatora.źródło
WYJŚCIA
źródło
Składnia find w mongodb jest następująca
i drugie zapytanie, które napisałeś
w tym użyłeś
$elemMatch
operatora w części zapytania, natomiast jeśli użyjesz tego operatora w części projekcji, otrzymasz pożądany wynik. Możesz zapisać swoje zapytanie jakoTo da pożądany rezultat.
źródło
"shapes.color":"red"
w parametrze zapytania (pierwszy parametr metody find) nie jest konieczne. Możesz go zastąpić{}
i uzyskać te same wyniki.Dzięki JohnnyHK .
Tutaj chcę tylko dodać bardziej złożone użycie.
źródło
Musisz tylko uruchomić zapytanie
wyjście tego zapytania to
zgodnie z oczekiwaniami, poda dokładne pole z tablicy, które pasuje do koloru: „czerwony”.
źródło
wraz z projektem $ bardziej odpowiednie będą inne mądre elementy pasujące do siebie razem z innymi elementami w dokumencie.
źródło
Podobnie można znaleźć dla wielokrotności
źródło
$match
zmniejszyć przestrzeń, a następnie$filter
zachować to, co chcesz, nadpisując pole wejściowe (użyj danych wyjściowych$filter
pola on,shapes
aby$project
wrócić doshapes
. Uwaga dotycząca stylu: najlepiej nie używać nazwy pola jakoas
argumentem, ponieważ może to prowadzić do nieporozumień później$$shape
i$shape
wolę.zz
jakoas
pola, ponieważ tak naprawdę wyróżnia.źródło
Użyj funkcji agregacji i
$project
uzyskaj określone pole obiektu w dokumenciewynik:
źródło
Chociaż pytanie zostało zadane 9,6 lat temu, było to ogromną pomocą dla wielu osób, a ja jestem jedną z nich. Dziękujemy wszystkim za wszystkie pytania, wskazówki i odpowiedzi. Pobranie jednej z odpowiedzi tutaj. Odkryłem, że poniższej metody można również użyć do wyświetlenia innych pól w dokumencie nadrzędnym. Może to być pomocne dla kogoś.
W przypadku poniższego dokumentu konieczne było sprawdzenie, czy pracownik (emp # 7839) ma ustawioną historię urlopów na rok 2020. Historia urlopów jest implementowana jako dokument osadzony w nadrzędnym dokumencie pracownika.
źródło