MongoDB

Baza pytań rekrutacyjnych i wiedzy. Filtruj, szukaj i sprawdzaj swoją wiedzę.

Tematy

Odpowiedź

Dokument to rekord w formacie podobnym do JSON (BSON) z parami klucz‑wartość, który może zawierać obiekty zagnieżdżone i tablice. Kolekcje przechowują dokumenty, a schemat jest elastyczny. Modelowanie danych polega głównie na osadzaniu (embedding) lub referencjonowaniu (referencing) w zależności od wzorców dostępu.

mediumindexcompound-indexperformance+1

Odpowiedź

Indeksy w MongoDB przechowują uporządkowane klucze, aby baza mogła szybko znaleźć pasujące dokumenty bez pełnego skanu kolekcji. Są indeksy jedno‑ i wielopolowe, multikey, tekstowe oraz geospatial. Indeksy przyspieszają odczyt, ale kosztują miejsce/pamięć i spowalniają zapisy.

mediumembeddingreferencingschema-design+1

Odpowiedź

Embedding zapisuje powiązane dane wewnątrz jednego dokumentu, co daje szybkie odczyty i atomowe aktualizacje, ale grozi dużymi dokumentami i duplikacją. Referencing przechowuje identyfikatory do innych dokumentów/kolekcji, zmniejsza duplikację i wspiera duże relacje, ale wymaga dodatkowych zapytań lub $lookup.

hardaggregationpipelinemongodb

Odpowiedź

Pipeline agregacji przetwarza dokumenty przez uporządkowane etapy takie jak $match, $group, $project czy $sort. Każdy etap transformuje strumień i przekazuje wynik do następnego, umożliwiając złożone analizy podobne do SQL.

[
  { "$match": { "status": "paid" } },
  { "$group": { "_id": "$customerId", "total": { "$sum": "$amount" } } },
  { "$sort": { "total": -1 } }
]
hardreplicationshardingscalability+1

Odpowiedź

Replica set zapewnia wysoką dostępność: jedna instancja primary replikuje dane do secondary z automatycznym failoverem. Sharding daje skalowanie horyzontalne: dane są dzielone na shard’y według klucza shardowania i routowane przez mongos. Często stosuje się oba naraz.

Odpowiedź

Dokument to rekord w formacie podobnym do JSON (BSON) z polami; kolekcja to zbiór dokumentów (jak tabela, ale schemat jest elastyczny). Dokumenty zwykle mają `_id` jako główny identyfikator.

Odpowiedź

Embeduj, gdy dane należą do rodzica i zwykle są czytane razem (jedno zapytanie, atomowa aktualizacja w jednym dokumencie). Referencje dawaj, gdy dane są duże, współdzielone lub rosną bez ograniczeń.

easyobjectididmongodb

Odpowiedź

ObjectId to 12-bajtowy identyfikator często używany jako `_id`. Zawiera timestamp i inne informacje zapewniające unikalność; nie jest idealnie sekwencyjny, ale zwykle jest „mniej więcej” uporządkowany czasowo.

Odpowiedź

Dla indeksu `{a: 1, b: 1, c: 1}` zapytania mogą efektywnie używać lewego prefiksu: (a), (a,b), (a,b,c). Jeśli pomijasz `a`, indeks jest dużo mniej przydatny dla takiego zapytania.

db.users.createIndex({ orgId: 1, email: 1 })

// uses prefix (orgId, email)
db.users.find({ orgId: 1, email: "[email protected]" })

Odpowiedź

To sekwencja etapów (`$match`, `$group`, `$project`, ...), która przetwarza dokumenty i liczy agregaty. Używa się do raportów, grupowania, filtrowania i kształtowania danych po stronie serwera.

db.orders.aggregate([
  { $match: { status: "PAID" } },
  { $group: { _id: "$customerId", total: { $sum: "$amount" } } }
])
mediumttlindexretention

Odpowiedź

TTL index automatycznie usuwa dokumenty po czasie na podstawie pola daty (albo stałego czasu wygaśnięcia). Przydaje się do sesji, tokenów, danych tymczasowych i logów z retencją.

Odpowiedź

W replica secie wybierany jest nowy primary, gdy obecny padnie. Write concern określa, kiedy zapis uznajesz za potwierdzony (np. majority), a read concern — jakiej spójności wymagasz przy odczycie. To kompromis między spójnością, opóźnieniem i dostępnością.

Odpowiedź

Dobry shard key ma wysoką kardynalność i dobre rozłożenie oraz pasuje do typowych zapytań. Typowo zły wybór to klucz rosnący monotonnie (np. timestamp), który robi hotspoty na jednym shardzie.

Odpowiedź

Są przydatne, gdy potrzebujesz atomowych zmian na wielu dokumentach/kolekcjach. Koszt to większy narzut i mniejsza wydajność niż operacje single-document; jeśli się da, modeluj dane tak, by unikać multi-doc transakcji.

Odpowiedź

`skip` musi „przejść” przez wiele dokumentów, więc dalekie strony są coraz wolniejsze. Lepszy wzorzec to paginacja range/seek (np. po `_id` albo indeksowanym createdAt) używając „większe niż ostatnie” + sortowanie.

db.posts.find({ _id: { $gt: lastId } })
  .sort({ _id: 1 })
  .limit(20)

Odpowiedź

`$set` ustawia wartość pola (i tworzy je, jeśli nie istnieje). Aktualizuje tylko wybrane pola, zamiast podmieniać cały dokument.

Odpowiedź

Projection to wybór tylko części pól do zwrócenia (include/exclude). Zmniejsza payload, poprawia wydajność i ogranicza przypadkowe ujawnianie danych.

db.users.find(
  { active: true },
  { email: 1, name: 1, _id: 0 }
)

Odpowiedź

Upsert oznacza „update albo insert”: jeśli żaden dokument nie pasuje do filtra, MongoDB wstawi nowy dokument (na podstawie update) zamiast aktualizować.

Odpowiedź

Dokumenty mają limit rozmiaru (16MB), a duże tablice powodują puchnięcie dokumentu, większy IO i wolniejsze update’y. Mogą też tworzyć hot documents i contention; lepiej wydzielić kolekcję albo stosować bucketing dla nieograniczonych list.

hardchange-streamsoplogreplica-set+1

Odpowiedź

Change Streams pozwalają subskrybować zmiany w czasie rzeczywistym (insert/update/delete) w kolekcji/bazie. Wymagają replica seta (lub sharded clustra), bo opierają się o oplog.

Odpowiedź

`$push` dopisuje wartość do tablicy (pozwala na duplikaty). `$addToSet` dodaje tylko wtedy, gdy wartość jeszcze nie istnieje (jak zbiór, bez duplikatów).

Odpowiedź

Unique index wymusza, że dwa dokumenty nie mogą mieć tej samej wartości dla indeksowanego klucza/kluczy. Bez niego sprawdzenia w aplikacji mogą się „wyścignąć” i utworzyć duplikaty przy współbieżności.

db.users.createIndex({ email: 1 }, { unique: true })

Odpowiedź

`$lookup` łączy dokumenty z innej kolekcji (jak left join). Pułapka: joiny mogą być drogie przy dużej skali; zadbaj o indeksy na kluczach łączenia i rozważ denormalizację/embedding, jeśli to pasuje.

Odpowiedź

`w:1` potwierdza zapis, gdy primary go przyjmie (mniejsza latencja, ale większe ryzyko przy failover). `w:"majority"` czeka na replikację do większości węzłów (większa trwałość, większa latencja).

Odpowiedź

Jeśli update powoduje wzrost dokumentu ponad przydzielone miejsce, MongoDB może przenieść dokument w nowe miejsce, co dokłada IO i fragmentację. Unikaj nieograniczonego wzrostu, aktualizuj „in place” gdy się da i modeluj dane tak, by rozmiar dokumentu był stabilny.

Odpowiedź

Read preference kontroluje, skąd idą odczyty w replica secie (np. `primary`, `secondary`, `secondaryPreferred`). Odczyty z secondary mogą odciążyć primary, ale możesz dostać lekko nieaktualne dane zależnie od laga replikacji i read concern.

Odpowiedź

Text index umożliwia full-text search zapytaniem `$text` oraz podstawowe stemming/scoring. Ograniczenia: można mieć tylko jeden text index na kolekcję i to mniej możliwości niż w dedykowanych silnikach wyszukiwania (zaawansowany ranking, fuzzy search).

mediummongoschema-validationjson-schema+1

Odpowiedź

Walidacja schematu (np. JSON Schema) odrzuca niepoprawne dokumenty przy zapisie, co chroni jakość danych. Pomaga przy refaktorach i gdy wiele serwisów zapisuje do tej samej kolekcji, ale reguły muszą być kompatybilne wstecz (w migracji pozwól na stary i nowy kształt).

Odpowiedź

`local` może zwrócić dane, które są na nodzie, z którego czytasz (szybko, ale mogą nie być jeszcze zreplikowane). `majority` zwraca dane potwierdzone przez większość członków replica seta, co daje mocniejszą spójność kosztem zwykle większej latencji.

Odpowiedź

Gdy zapytanie nie zawiera shard key (lub jego sensownego prefixu), `mongos` może musieć odpytywać wiele shardów i scalić wyniki (“scatter-gather”), co zwiększa latencję i obciążenie. Unikasz tego dobierając shard key zgodny z typowymi wzorcami zapytań i pisząc zapytania, które go używają.

Odpowiedź

Gwarantuje, że pojedynczy zapis na jednym dokumencie jest „wszystko albo nic”: odczyty nie zobaczą „połowy” zmian. Nie daje atomowości na wielu dokumentach/kolekcjach — do tego potrzebujesz transakcji.

Odpowiedź

Covered query to takie zapytanie, które da się obsłużyć tylko z indeksu, bez pobierania całego dokumentu. Jest szybsze, bo nie trzeba doczytywać dokumentów z dysku/pamięci. Dzieje się tak, gdy filtr i zwracane pola są w tym samym indeksie (i nie potrzebujesz innych pól).

db.users.createIndex({ email: 1, createdAt: 1 })

// Only indexed fields are returned => can be covered
db.users.find({ email: "[email protected]" }, { _id: 0, email: 1, createdAt: 1 })

Odpowiedź

Wczesny `$match` zmniejsza liczbę dokumentów przepływających przez kolejne etapy, więc pipeline ma mniej pracy. Jeśli `$match` jest na początku i pasuje do indeksu, MongoDB może użyć indeksu. Wczesny `$project` zmniejsza „payload”, co często zmniejsza zużycie pamięci i sieci.

Odpowiedź

Pojawiają się, gdy równoległe transakcje próbują zmienić te same dokumenty/klucze, więc jedna z nich musi się wycofać, żeby zachować izolację. Aplikacja powinna to traktować jako błąd do ponowienia: ponów całą transakcję (z backoffem), trzymaj transakcje krótkie i rób efekty uboczne idempotentne, żeby retry było bezpieczne.

Odpowiedź

Balancer przenosi chunki między shardami, żeby wyrównać rozkład danych. Migracje zużywają CPU/IO/sieć i potrafią podnieść latencję, szczególnie gdy przenoszą duże lub „gorące” chunki. Zmniejsz wpływ dobrym shard key (bez hotspotów), monitoringiem migracji, uruchamianiem ich poza szczytem oraz (gdy ma sens) strefami i pre-splittingiem.

Odpowiedź

Osadzaj, gdy dane dziecka są zwykle czytane razem z rodzicem i nie rosną bez limitu (np. zamówienie z pozycjami). Embedding daje mniej zapytań i atomowe aktualizacje w jednym dokumencie. Referencje wybieraj przy relacjach many‑to‑many lub nieograniczonym wzroście.

Odpowiedź

Indeks TTL automatycznie usuwa dokumenty po określonym czasie na podstawie pola daty. Używa się go do danych wygasających (sesje, OTP, tymczasowe logi), aby uniknąć ręcznego sprzątania.

db.sessions.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 })
mediummongocapped-collectionstorage+1

Odpowiedź

Capped collection ma stały rozmiar i działa jak bufor cykliczny: gdy się zapełni, najstarsze dokumenty są nadpisywane. Przydaje się do logów, cache i strumieni, gdy chcesz ograniczoną przestrzeń i zachowanie kolejności wstawień.

mediummongochange-streamscdc+1

Odpowiedź

Change streams pozwalają obserwować zmiany w czasie rzeczywistym (insert/update/delete) w kolekcji lub bazie, podobnie do CDC. Przydają się do reaktywnych workflowów, invalidacji cache i architektur event‑driven.

mediummongoconsistencyread-concern+1

Odpowiedź

Read concern kontroluje spójność/zakres widoczności odczytów (np. local, majority). Write concern kontroluje trwałość i potwierdzenie zapisów (np. w:1, majority). To trade‑off między latencją a mocniejszymi gwarancjami.

Odpowiedź

`primary` czyta tylko z primary (mocniejsza spójność). `secondary` pozwala czytać z secondary (mniejsza latencja i odciążenie, ale możliwe „stare” dane). Są też tryby typu `primaryPreferred` i `secondaryPreferred`.

Odpowiedź

Gdy primary jest niedostępny, secondary przeprowadzają elekcję, wybierając nowe primary na podstawie kryteriów elekcji. W tym czasie zapisy są niedostępne, a część odczytów może być nieaktualna. Po elekcji nowe primary przyjmuje zapisy.

Odpowiedź

`$lookup` wykonuje left outer join między kolekcjami w pipeline agregacji. Typowa pułapka to duży fan‑out joinu, który bywa wolny i pamięciożerny. Warto mieć indeksy na kluczach łączenia i filtrować jak najwcześniej.

Odpowiedź

Indeksy tekstowe umożliwiają full‑text search na polach tekstowych z tokenizacją i stemmingiem. Są przydatne do wyszukiwania, ale mają ograniczenia (np. tylko jeden indeks tekstowy na kolekcję i mniejsza elastyczność niż wyspecjalizowane wyszukiwarki).

Odpowiedź

Indeks unique wymusza unikalność dla dokumentów objętych indeksem. Indeks sparse obejmuje tylko dokumenty, które mają dane pole. Indeks partial obejmuje dokumenty spełniające warunek filtra. Możesz je łączyć, by wymuszać unikalność tylko dla części danych.