Pobieranie informacji z bazy danych jest chyba jedną z najczęściej wykonywanych operacji. W bazach relacyjnych korzystamy do tego celu z polecenia SELECT. W przypadku MongoDB musimy przygotować odpowiedni obiekt, którym opiszemy jakie dane(dokumenty) chcemy dostać. Jak on wygląda w praktyce i jakie ma opcje?
W poście korzystam z danych wygenerowanych w MongoDB Atlas. Korzystam z bazy danych sample_mflix i kolekcji movies.
Inne wpisy z tej serii
- Łączenie z bazą danych
Pobieranie danych
Dane z kolekcji pobieramy wykorzystując metodę collection.find(query, options). Najprościej zacząć od wywołania tej metody bez przekazywania żadnych parametrów, dzięki czemu pobierzemy wszystkie dokumenty z kolekcji. Oczywiście, jeżeli ilość dokumentów jest duża, może to spowolnić pracę systemu. Warte wspomnienia jest, iż jako rezultat operacji nie dostajemy tablicy dokumentów tylko pojedynczy obiekt. Aby dostać się do danych musimy skorzystać z udostępnionych przez ten obiekt metod:
Cursor
Jak już wspomniałem rezultatem operacji find nie jest tablica z gotowymi danymi tylko pewien obiekt z którego możemy potem wyciągnąć dane. Ten obiekt nazywa się Cursor i będziemy z niego korzystać zawsze, kiedy będziemy operować na danych zwróconych z kolekcji. Część z dostępnych metod poznaliśmy już chwilę temu, czyli: cursor.count(), cursor.hasNext(), cursor.next(), cursor.limit(). Inną przydatną metodą jest cursor.toArray() dzięki której jesteśmy w stanie przekształcić naszą kolekcję do postaci tablicy i na przykład zwrócić w endpoincie.
Inne metody możecie sprawdzić tutaj.
Filtrowanie danych
Najważniejszym tematem przy pobieraniu danych jest ich filtrowanie. Nie potrzebujemy zawsze pobierać wszystkich dokumentów, a w 90% przypadków będziemy potrzebować tylko konkretnych danych. Aby filtrować dane musimy skorzystać z pierwszego parametru funkcji find. Podajemy tam obiekt, w którym przekazujemy jakie dane nas interesują np.: konkretny rok:
Możemy też filtrować dane w zagnieżdżonych dokumentach. Robimy to przy pomocy tzw.: dot notation czyli np.: awards.win czyli odwołujemy się do pola win wewnątrz dokumentu awards.
Kolejna funkcjonalność to możliwość korzystania ze specjalnych operatorów. Jednym z przykładów takiego operatora jest $gt, który pozwala zwrócić wyniki o wartości większej niż podana przy parametrze. Rozszerzają one możliwości filtrowania i pozwalają na tworzenie zaawansowanych zapytań. Inne przydatne operatory można znaleźć tutaj.
Trzeba uważać w przypadku tabel, ponieważ poniższe wyrażenie spowoduje, iż dostaniemy wyniki, które w polu countries posiadają dokładnie te dwie wartości w podanej kolejności.
Jeśli chcemy stworzyć bardziej zaawansowane zapytanie dla tablic, musimy skorzystać ze specjalnych operatorów. Ciekawym operatorem jest operator $size który pozwala wybrać dokumenty, które mają pole o określonym rozmiarze. Natomiast $elemMatch pozwala na tworzenie bardzo zaawansowanych zapytań.
Projekcja danych
Do tej pory pobieraliśmy wszystkie możliwe pola z dokumentu. Jednak im więcej pól tym większy rozmiar dokumentów, a nie zawsze tego potrzebujemy. Możemy tym sterować przy pomocy mechanizmu projekcji. Aby to zrobić musimy skorzystać z drugiego parametru funkcji find() czyli options. Jednym z parametrów jest obiekt projection. W tym obiekcie podajemy jakie pola chcemy dostać w rezultacie zapytania. Inne przydatne parametry w obiekcie options to np.: limit, sort czy skip, a resztę znajdziecie tutaj.
W tym przykładzie jako rezultat dostaniemy obiekty z polem year oraz _id. Pole _id jest domyślnie dodawane do każdego rezultatu i jeżeli go nie potrzebujemy to musimy go wyłączyć.
W ten sam sposób możemy wyłączyć dowolne pole, jeżeli nie chcemy go otrzymać w odpowiedzi.
Zapytanie tym razem spowoduje, iż dostaniemy wszystkie pola oprócz roku. Podobnie jak przy filtrowaniu możemy dokonywać projekcji na zagnieżdżonych dokumentach. Aby to zrobić musimy skorzystać ponownie z zapisu z kropką np.:
Zapis spowoduje, iż w odpowiedzi dostaniemy pole imdb z polem rating. Mamy możliwość również operowania na tablicach, dla których zostały zdefiniowane specjalne operatory: $elemMatch, $slice, i $.
Przy pomocy operatora $slice możemy ustalić ile pól z tablicy chcemy, żeby zostało zwrócone. W powyższym przykładzie otrzymamy jedno pole licząc od końca. Operator $ powoduje, iż zwrócimy tylko pierwsze wystąpienie pasujące do zapytania. Musimy tylko pamiętać, iż wymagane jest wtedy filtrowanie danego pola.
$elemMatch jest bardziej elastyczny i pozwala na tworzenie elastycznych zapytań, które zdefiniują, kiedy pola mają być zwrócone.
findOne
Na sam koniec warto jeszcze wspomnieć o metodzie findOne. Dzięki temu otrzymamy pierwszy dokument z kolekcji, który spełnia zadane przez nas parametry.
W odróżnieniu od metody find tutaj nie dostajemy obiektu Cursor tylko od razu rezultat. Więc choćby jeżeli da się uzyskać pojedynczy obiekt przy pomocy find to tutaj szybciej dostaniemy się do wyniku.