MongoDB posiada bardzo ciekawą funkcjonalność w postaci automatycznego usuwania danych po upłynięciu określonego czasu. Wystarczy w tym celu utworzyć w kolekcji indeks TTL (ang. time to live). Dzięki temu można w niezwykle prosty sposób zaimplementować wygasające dane.
Indeksy TTL możemy tworzyć na dwa różne sposoby. Możemy spowodować usunięcie dokumentu po określonej liczbie sekund lub o określonym przez nas czasie.
Usuwanie dokumentów po upłynięciu określonego czasu
W tym przypadku należy utworzyć indeks na polu zawierającym datę, podając czas w sekundach, po jakim dokument zostanie usunięty.
Wyobraźmy sobie następującą, uproszczoną sytuację: w naszej aplikacji chcemy udostępniać jakieś zasoby, jednak wprowadzamy limit dla adresu IP. Powiedzmy, że użytkownik może coś pobrać raz na 10 minut. W naszej bazie informacje o fakcie pobrania będziemy przechowywali w następującej kolekcji:
use downloads; db.waiting.insert({createdAt: new Date(), ip: "111.222.333.444"}); db.waiting.insert({createdAt: new Date(), ip: "555.666.777.888"});
Jeśli chcemy aby nasze rekordy były kasowane z niej po 10 minutach wystarczy, że nałożymy następujący indeks TTL na pole z datą:
db.waiting.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 600 } )
Po upłynięciu 600 sekund rekord zostanie automatycznie skasowany.
Usuwanie dokumentów o określonym czasie
Indeks TTL możemy także skonfigurować odwrotnie, tj. podając dokładny czas, w jakim dokument ma zostać skasowany. W tym celu należy na pole z datą ustawić indeks z wartością expireAfterSeconds
ustawioną na 0:
db.premium.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
Jeśli data ustawiona w polu expireAt
minie, to dokument zostanie automatycznie skasowany.
Kilka dodatkowych informacji
W przypadku korzystania z opisanej funkcjonalności, warto pamiętać o tym, że:
- Nie można nałożyć indeksu TTL na pole
_id
. - Indeks TTL nie może być ustawiony na pole, które posiada już inny indeks.
- Dokument nie zostanie usunięty, jeśli nie będzie on posiadał zaindeksowanego pola (nie będzie w nim istniało pole z datą).
- Dokument nie wygaśnie, jeśli zaindeksowane pole nie będzie pojedynczą datą lub tablicą dat w formacie BSON.
- Indeksy TTL mogą być tylko proste (muszą składać się z jednego pola).
- Jeśli indeks TTL został nałożony na tablicę, w której są daty, to dokument wygaśnie po uwzględnieniu najwcześniejszej z nich.
- Nie można nałożyć indeksu TTL w capped collection (specjalna kolekcja, w której dane nadpisują się automatycznie).
- Nie można użyć
ensureIndex()
w celu zmiany parametruexpireAfterSeconds
. - W przypadku tworzenia indeksu TTL typu background, dokumenty mogą być kasowane już w trakcie jego budowania. Jeśli będziemy go tworzyć jako foreground, dokumenty będą kasowane po jego zbudowaniu.
- W przypadku używania indeksu TTL na zreplikowanych bazach, zostanie on uaktywniony tylko na primary. Dane zostaną usunięte z serwerów secondary podczas synchronizacji.
Dlaczego dane nie kasują się od razu?
Przeprowadzając testy indeksów TTL z ustawionymi krótkimi czasami usunięcia dokumentów (np. kilkadziesiąt sekund) można dojść do wniosku, że nie wygasają one tak jak powinny. Dzieje się tak dlatego, że proces kasujący dane jest wywoływany co 60 sekund. Z tego względu dokumenty mogą zostać usunięte w krótkim czasie po upłynięciu terminu (działanie nie rozpoczyna się natychmiastowo).