Dropdown “filter per kategori” di halaman katalog perlu diisi daftar kategori yang benar-benar ada di data — bukan daftar tebakan yang ditulis manual di kode. Mengambil seluruh document lalu mengumpulkan nilainya di aplikasi adalah pemborosan: data yang sama dikirim berkali-kali hanya untuk dibuang. Method distinct() mengerjakan pengumpulan nilai unik ini di sisi server dan hanya mengirim hasil akhirnya. Chapter ini menguji distinct() pada field biasa, field array, dan nested document.
Peta materi Chapter ini:
distinct()pada field biasa dan perilakunya terhadap field yang hilang.- Penggunaan pada field array yang otomatis diratakan (flatten).
distinct()pada nested path dan dengan filter tambahan.
Nilai Unik Satu Field #
Siapkan katalog dengan stok berupa nested document { gudang, toko } — Kamus Bahasa Indonesia tetap memakai angka biasa dan tidak memiliki kategori:
use latihan_query
db.buku.drop()Output yang Dihasilkan:
switched to db latihan_query
truedb.buku.insertMany([
{ judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, stok: { gudang: 8, toko: 4 }, kategori: "fiksi", tag: ["fiksi", "sastra", "pengarang Indonesia"], rating: 4.7 },
{ judul: "Bumi", penulis: "Tere Liye", harga: 89000, stok: { gudang: 20, toko: 5 }, kategori: "fiksi", tag: ["fiksi", "remaja"], rating: 4.5 },
{ judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, stok: { gudang: 15, toko: 3 }, kategori: "nonfiksi", tag: ["nonfiksi", "filsafat", "pengembangan diri"], rating: 4.8 },
{ judul: "Atomic Habits", penulis: "James Clear", harga: 115000, stok: { gudang: 25, toko: 5 }, kategori: "nonfiksi", tag: ["nonfiksi", "pengembangan diri", "terjemahan"], rating: 4.6 },
{ judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, stok: { gudang: 6, toko: 3 }, kategori: "fiksi", tag: ["fiksi", "remaja", "distopia"], rating: 4.3 },
{ judul: "Kamus Bahasa Indonesia", penulis: "Badan Bahasa", harga: 55000, stok: 4, tag: ["referensi", "bahasa"] }
])Output yang Dihasilkan:
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad3902f221c1d55a3a07446'),
'1': ObjectId('6ad3902f221c1d55a3a07447'),
'2': ObjectId('6ad3902f221c1d55a3a07448'),
'3': ObjectId('6ad3902f221c1d55a3a07449'),
'4': ObjectId('6ad3902f221c1d55a3a0744a'),
'5': ObjectId('6ad3902f221c1d55a3a0744b')
}
}Bentuk dasarnya: db.<collection>.distinct("<field>"). Kumpulkan daftar kategori:
db.buku.distinct("kategori")Output yang Dihasilkan:
[ 'fiksi', 'nonfiksi' ]Hasilnya array nilai unik: 'fiksi' dari tiga buku dan 'nonfiksi' dari dua buku menyatu jadi satu entri. Perhatikan bahwa Kamus Bahasa Indonesia tidak menyumbang apa pun — document tanpa field yang diminta tidak menghasilkan nilai, dan tidak ada entri null yang muncul. Bandingkan dengan query { kategori: null } di Chapter Null dan Missing Fields yang justru menangkap document seperti itu.
Field Array: Otomatis Rata #
distinct() pada field array bekerja dengan cara yang membantu: setiap elemen array dihitung sebagai nilai tersendiri, lalu duplikatnya dibuang:
db.buku.distinct("tag")Output yang Dihasilkan:
[
'bahasa',
'distopia',
'fiksi',
'filsafat',
'nonfiksi',
'pengarang Indonesia',
'pengembangan diri',
'referensi',
'remaja',
'sastra',
'terjemahan'
]Enam belas slot tag tersebar di enam buku, tetapi hasilnya hanya 11 nilai — 'fiksi' yang dipakai tiga buku dan 'pengembangan diri' yang dipakai dua buku masing-masing hanya muncul sekali. Hasil berupa array JavaScript biasa, sehingga properti dan method array bisa langsung dipakai, misalnya untuk menghitung jumlahnya:
db.buku.distinct("tag").lengthOutput yang Dihasilkan:
11Nested Path dan Filter Tambahan #
Dot notation berlaku untuk menjangkau field di dalam nested document:
db.buku.distinct("stok.gudang")Output yang Dihasilkan:
[ 6, 8, 15, 20, 25 ]Lima nilai stok gudang yang unik terkumpul. Kamus Bahasa Indonesia kembali absen: field stok-nya berupa angka, bukan object, sehingga path stok.gudang tidak bisa dijangkau — perilaku yang sama dengan projection nested di Chapter Projection.
Argumen kedua distinct() adalah filter yang membatasi document mana saja yang ikut dihitung. Ambil daftar penulis dari buku fiksi saja:
db.buku.distinct("penulis", { kategori: "fiksi" })Output yang Dihasilkan:
[ 'Leila S. Chudori', 'Tere Liye' ]James Clear, Henry Manampiring, dan Badan Bahasa tidak muncul karena buku mereka tersaring oleh { kategori: "fiksi" } sebelum nilai dikumpulkan. Filter ini menerima operator query biasa — rentang harga, $in, regex — persis seperti filter find().
Rangkuman #
distinct("field")mengembalikan array nilai unik dari seluruh collection; document tanpa field tersebut tidak menyumbang nilai.- Pada field array, setiap elemen dihitung sebagai nilai tersendiri dan duplikat dibuang otomatis.
- Dot notation (
"stok.gudang") menjangkau nested document; document dengan bentuk field tidak cocok dilewati. - Argumen kedua adalah filter biasa untuk membatasi sumber penghitungan.
- Hasil berupa array JavaScript —
.length,.sort(), dan kawan-kawan bisa langsung dipakai.