Empat sensor cuaca, satu titik data tiap tiga puluh menit, tanpa jeda: dalam sebulan saja terkumpul hampir 6.000 pengukuran per sensor. Menyimpannya di collection biasa terasa sah — insert-nya pun sama saja — tetapi kita kehilangan tiga keuntungan besar time series collection: pengelompokan otomatis titik-titik data ke dalam bucket yang terkompresi, index otomatis pada pasangan meta-waktu, dan dukungan penuh operator analisis waktu. Bagian ini merancang fondasinya: satu collection sensor_cuaca dengan metaField yang tepat, lalu memverifikasi bahwa MongoDB benar-benar memperlakukannya sebagai time series.

Keputusan Desain: MetaField dan Granularity #

Dua keputusan menentukan kualitas seluruh proyek ini, dan keduanya harus diambil sekarang.

Keputusan pertama: apa yang menjadi metaField. Isi field inilah identitas seri data — nilai yang sama dari satu pengukuran ke pengukuran berikutnya. Untuk sensor cuaca, identitas seri adalah sensornya sendiri: sensor_id dan kota. MongoDB mengelompokkan pengukuran dari meta yang sama ke dalam satu bucket, jadi meta yang stabil membuat bucket padat dan kompresi maksimal. Kebalikannya, nilai yang berubah tiap titik (suhu, kelembapan) wajib berada di luar metaField — kalau masuk, setiap pengukuran membangun bucket sendiri dan keuntungan pengelompokan menguap.

Keputusan kedua: granularity. Opsi ini memberi tahu MongoDB seberapa rapat titik data datang — "seconds", "minutes", atau "hours" — dan dipakai untuk mengoptimalkan jendela internal bucket. Sensor kita menulis tiap 30 menit, sehingga "minutes" adalah pilihan yang tepat.

Skrip buat-collection.js merangkai semuanya:

js

Jalankan dari folder proyek:

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

Output yang Dihasilkan:

text
database direset: proyek_sensor
== membuat collection sensor_cuaca ==
{ ok: 1 }
== verifikasi tipe collection ==
name : sensor_cuaca
type : timeseries
{
  timeseries: {
    timeField: 'ts',
    metaField: 'sensor',
    granularity: 'minutes',
    bucketMaxSpanSeconds: 86400,
    fixedBucketing: true
  }
}
== index yang terpasang ==
  sensor_1_ts_1 -> {"sensor":1,"ts":1}

Mari kita bedah keluarannya:

  1. type: 'timeseries': getCollectionInfos() mengonfirmasi collection ini bukan collection biasa — kita tidak membuatnya lewat insert pertama, melainkan createCollection dengan opsi timeseries.
  2. bucketMaxSpanSeconds: 86400: satu bucket menampung pengukuran dari satu sensor maksimal sepanjang 24 jam — nilai yang diturunkan otomatis dari granularity: "minutes".
  3. sensor_1_ts_1: index majemuk { sensor: 1, ts: 1 } terpasang tanpa kita minta. Inilah index otomatis time series: meta di depan, waktu di belakang — persis bentuk yang dibutuhkan query “sensor ini, rentang waktu ini”.

Kenapa Bukan Collection Biasa #

Perbandingan singkat memperjelas posisi kita:

AspekCollection biasaTime series collection
Index pertamaHarus dibuat manual{ meta, time } otomatis
PenyimpananSatu document per pengukuranBucket terkompresi per sensor
Update/deleteBebasTerbatas (data historis memang jarang diubah)
_id per pengukuranDikelola sendiriMuncul otomatis di hasil baca, tidak kita tulis
Cocok untukData transaksional yang berubahData urut waktu yang append-only

Baris _id layak diperhatikan: pada time series kita tidak menulis _id sendiri — MongoDB menyediakannya pada hasil pembacaan, dan kita tidak mengandalkannya sebagai kunci data. Identitas satu pengukuran adalah pasangan sensor + ts.

Dengan collection siap, Bagian 2 mengisinya: 500 pengukuran deterministik yang menjadi bahan analisis seluruh proyek.