Data sensor tumbuh tanpa batas, tetapi nilai informasinya tidak: rata-rata per jam bulan lalu tetap berharga, sementara pengukuran mentah per 30 menit dari dua tahun lalu jarang dibaca siapa pun. Retensi adalah keputusan tentang umur data — dan di time series collection, MongoDB menyediakan dua mekanisme pelengkapnya: TTL untuk menghapus data lawas secara otomatis, dan $merge untuk meninggalkan ringkasan. Bagian penutup ini memasang keduanya, membuktikan TTL benar-benar bekerja, lalu menutup proyek dengan bukti performa dan suite tes.

Skrip Retensi #

retensi.js melakukan tiga hal: memasang lalu melepas TTL pada collection utama (dataset kita historis — TTL 7 hari akan menghapus semuanya), membuktikan TTL nyata pada collection uji kecil, dan membangkitkan ringkasan harian:

js

Jalankan (skrip menunggu 70 detik untuk siklus TTL — itu memang bagian dari pembuktian):

bash
mongosh "mongodb://127.0.0.1:27017/?directConnection=true" --file src/retensi.js

Output yang Dihasilkan (metadata $clusterTime dipangkas agar ringkas):

text
== collMod: pasang expireAfterSeconds 604800 (7 hari) ==
{ ok: 1 }
opsi collection sekarang:
{
  expireAfterSeconds: Long('604800'),
  timeseries: {
    timeField: 'ts',
    metaField: 'sensor',
    granularity: 'minutes',
    bucketMaxSpanSeconds: 86400,
    fixedBucketing: true
  }
}
== collMod: matikan TTL (expireAfterSeconds "off") ==
{ ok: 1 }
== uji TTL nyata pada sensor_tes_ttl ==
{ ok: 1 }
titik sebelum TTL: 2
menunggu 70 detik (TTL monitor berjalan tiap 60 detik)...
titik setelah TTL : 0
== downsampling: ringkasan per sensor per hari ($merge) ==
baris ringkasan: 12
   2026-01-01 BDG-07 Bandung     rata 25.78 °C maks 27.5 °C | 48 titik
   2026-01-01 JKT-01 Jakarta     rata 28.88 °C maks 30.5 °C | 48 titik
   2026-01-02 SBY-12 Surabaya    rata 31.01 °C maks 32.8 °C | 48 titik
   ...
   2026-01-03 YOG-03 Yogyakarta  rata 27.89 °C maks 30 °C | 29 titik

Tiga temuan penting dari keluaran ini:

  1. collMod menerima expireAfterSeconds: "off" — TTL bisa dilepas tanpa menghapus collection. Perhatikan juga mengapa TTL dilepas lagi: dataset kita bertanggal Januari 2026; dengan TTL 7 hari, seluruhnya kedaluwarsa dan akan terhapus pada siklus monitor berikutnya.
  2. TTL terbukti nyata: collection uji diisi dua titik ber-timestamp 26 jam lalu, collMod memasang TTL 30 detik, dan setelah menunggu satu siklus monitor (berjalan tiap 60 detik) jumlah titik menjadi 0. TTL pada time series bekerja di level bucket — bucket yang seluruh isinya lawas dihapus utuh.
  3. Downsampling menghasilkan 12 baris: 4 sensor × 3 hari, dengan whenMatched: "replace" menjadikan skrip aman diulang — ringkasan selalu yang termutakhir.

Bukti Performa #

uji-performa.js membandingkan empat query pada explain("executionStats") dan menutup dengan perbandingan working set:

js

Output yang Dihasilkan (bagian winningPlan ringkas — CLUSTERED_IXSCAN pertama menampilkan bentuk lengkapnya):

text
== JKT-01 sepanjang 1 Januari ==
{
  isCached: false,
  stage: 'CLUSTERED_IXSCAN',
  filter: { ... filter pada meta.sensor_id dan control.min/max/ts ... },
  nss: 'proyek_sensor.sensor_cuaca',
  direction: 'forward'
}
bucket cocok    : 1 | kunci diperiksa: 2 | bucket diperiksa: 5
pengukuran keluar: Long('48')
== JKT-01 tanpa rentang waktu ==
bucket cocok    : 3 | kunci diperiksa: 0 | bucket diperiksa: 12
pengukuran keluar: Long('125')
== tanpa filter ==
bucket cocok    : 12 | kunci diperiksa: 0 | bucket diperiksa: 12
pengukuran keluar: Long('500')
== index otomatis sensor_1_ts_1 ==
bucket cocok    : 1 | kunci diperiksa: 2 | bucket diperiksa: 1
pengukuran keluar: Long('48')
== perbandingan working set ==
sensor_cuaca    : 500 pengukuran | 12 bucket | data 6524 byte | terpakai 20480 byte
ringkasan_harian: 12 baris | data 1684 byte | terpakai 36864 byte

Empat baris “bucket cocok” itu menceritakan satu kisah:

  1. Sensor + rentang waktu (kunci diperiksa 2, bucket diperiksa 5): filter sensor memangkas lewat index otomatis, lalu rentang waktu menyaring bucket — 48 pengukuran keluar tanpa perlu menyentuh data lain.
  2. Sensor tanpa rentang (bucket diperiksa 12): tanpa batas waktu, seluruh 12 bucket harus dibuka meski hasilnya hanya 3 bucket milik sensor itu.
  3. Tanpa filter (semuanya diperiksa): tidak ada jalan lain — semua data keluar.
  4. Filter meta bentuk penuh (bucket diperiksa 1): saat filter sensor ditulis sebagai subdocument lengkap { kota, sensor_id } sesuai urutan tersimpan, index otomatis bekerja paling rapat — satu bucket, dua kunci.

Perbandingan working set menutup argumen retensi: 500 pengukuran mentah (6,5 KB data) direduksi menjadi 12 baris ringkasan (1,7 KB). Pada skala nyata rasio ini yang menjaga dashboard tahunan tetap cepat — kita membaca ringkasan, bukan miliaran titik mentah.

Suite Tes Penutup #

js

Suite ini menyiapkan datanya sendiri di database proyek_sensor_tes — termasuk mereplikasi generator deterministik untuk membandingkan rata-rata hasil server dengan hitungan lokal:

bash
mongosh "mongodb://127.0.0.1:27017/?directConnection=true" --file tests/semua-tes.js

Output yang Dihasilkan:

text
lulus - collection bertipe timeseries
lulus - timeField = ts
lulus - metaField = sensor
lulus - index otomatis sensor_1_ts_1 terpasang
lulus - total 500 pengukuran
lulus - 125 titik untuk SBY-12
lulus - field ts berupa Date
lulus - metaField sensor tersimpan
lulus - kota pada metaField benar
lulus - suhu numerik
lulus - kelembapan numerik
lulus - rata-rata suhu server = hitungan lokal (28.4608)
lulus - JKT-01 pada 1 Januari = 48 titik (interval 30 menit)
lulus - 24 kelompok jam pada 1 Januari
lulus - setiap jam berisi tepat 2 titik
lulus - ringkasan harian = 12 baris
lulus - 8 baris berisi 48 titik (2 hari penuh x 4 sensor)
lulus - collMod expireAfterSeconds diterima
lulus - opsi TTL tersimpan
lulus - TTL dapat dimatikan kembali
SEMUA TES LULUS

Dengan ini proyek — dan seluruh Course MongoDB — tuntas: data time series dari schema, penyimpanan, analisis, sampai retensi, semuanya berjalan dan teruji. Selamat menyelesaikan perjalanan panjangnya.