“Semua buku Tere Liye”, “novel remaja dari penerbit Yogyakarta”, “buku bertag sastra” — tiga pertanyaan itu diterjemahkan menjadi satu format yang sama: query filter, sebuah object yang memetakan field ke syarat nilainya. Filter adalah kosakata inti setiap operasi Read; find(), findOne(), sampai updateOne() dan deleteOne() di Chapter-Chapter berikutnya semuanya memakai bentuk yang sama. Chapter ini membangun kosakata itu dari fondasinya: kesamaan nilai, penggabungan beberapa syarat, field bersarang, dan field array.

Peta materi Chapter ini:

  • Kesamaan satu field: { field: nilai }.
  • Beberapa field dalam satu filter: AND implisit.
  • Dot notation untuk field di dalam nested document.
  • Kesamaan pada field array — termasuk jebakan pencocokan array utuh.

Kesamaan Satu Field #

Bentuk paling dasar sebuah filter adalah { field: nilai }: document dianggap cocok bila field tersebut tepat bernilai itu. Siapkan katalog — kali ini setiap buku membawa field penerbit berupa nested document, karena kita akan membedahnya sebentar lagi:

js
use latihan_crud
db.buku.drop()

Output yang Dihasilkan:

text
switched to db latihan_crud
true
js
db.buku.insertMany([
  { judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, stok: 12, kategori: "fiksi", tag: ["fiksi", "sastra"], rating: 4.7, penerbit: { nama: "Kepustakaan Populer Gramedia", kota: "Jakarta" } },
  { judul: "Bumi", penulis: "Tere Liye", harga: 89000, stok: 25, kategori: "fiksi", tag: ["fiksi", "remaja"], rating: 4.5, penerbit: { nama: "Gramedia Pustaka Utama", kota: "Jakarta" } },
  { judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, stok: 18, kategori: "nonfiksi", tag: ["filsafat", "pengembangan diri"], rating: 4.8, penerbit: { nama: "Kompas Penerbit", kota: "Jakarta" } },
  { judul: "Atomic Habits", penulis: "James Clear", harga: 115000, stok: 30, kategori: "nonfiksi", tag: ["pengembangan diri", "terjemahan"], rating: 4.6, penerbit: { nama: "Gramedia Pustaka Utama", kota: "Jakarta" } },
  { judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, stok: 9, kategori: "fiksi", tag: ["fiksi", "remaja"], rating: 4.3, penerbit: { nama: "Bentang Pustaka", kota: "Yogyakarta" } },
  { judul: "Kamus Bahasa Indonesia", penulis: "Badan Bahasa", harga: 55000, stok: 4, tag: ["referensi", "bahasa"], penerbit: { nama: "Balai Pustaka", kota: "Jakarta" } }
])

Output yang Dihasilkan:

text
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('6ad3876254468840ad504feb'),
    '1': ObjectId('6ad3876254468840ad504fec'),
    '2': ObjectId('6ad3876254468840ad504fed'),
    '3': ObjectId('6ad3876254468840ad504fee'),
    '4': ObjectId('6ad3876254468840ad504fef'),
    '5': ObjectId('6ad3876254468840ad504ff0')
  }
}

Dari sini kita memakai proyeksi { judul: 1 } — yang diperkenalkan di Chapter findOne() — agar keluaran hanya menampilkan judul. Filter pertama: semua buku Tere Liye:

js
db.buku.find({ penulis: "Tere Liye" }, { judul: 1 })

Output yang Dihasilkan:

text
[
  { _id: ObjectId('6ad3876254468840ad504fec'), judul: 'Bumi' },
  { _id: ObjectId('6ad3876254468840ad504fef'), judul: 'Rumah Kaca' }
]

Dua document cocok, dua lagi meski sama-sama fiksi tidak ikut karena penulisnya berbeda. Kesamaan di sini bersifat exact dan peka huruf besar-kecil: "tere liye" tidak akan cocok, dan angka 89000 tidak sama dengan string "89000".

Perhatikan juga document Kamus Bahasa Indonesia: buku tersebut sengaja tanpa field kategori. Terhadap pertanyaan kategori: "fiksi" buku tersebut tidak cocok — field yang tidak ada tidak pernah sama dengan nilai apa pun. Perilaku simetrisnya yang mengejutkan kita bedah di Chapter Comparison Operators.

Beberapa Field: AND Implisit #

Dua syarat cukup ditulis sebagai dua pasangan field-nilai dalam satu object — keduanya otomatis di-AND-kan:

js
db.buku.find({ kategori: "nonfiksi", harga: 89000 }, { judul: 1 })

Output yang Dihasilkan:

text
[
  { _id: ObjectId('6ad3876254468840ad504fed'), judul: 'Filosofi Teras' }
]

Hanya Filosofi Teras yang lolos: Atomic Habits memang nonfiksi tetapi harganya 115000, sedangkan Bumi sama-sama 89000 tetapi kategorinya fiksi. Satu field yang tidak cocok sudah cukup membuat seluruh document tidak lolos — itulah makna AND. Syarat boleh lebih dari dua; setiap pasangan tambahan mempersempit hasil.

Dot Notation untuk Field Bersarang #

Field di dalam nested document dijangkau dengan dot notation: "penerbit.kota" berarti field kota di dalam object penerbit. Tanda kutip wajib karena nama lengkapnya mengandung titik:

js
db.buku.find({ "penerbit.kota": "Yogyakarta" }, { judul: 1, penerbit: 1 })

Output yang Dihasilkan:

text
[
  {
    _id: ObjectId('6ad3876254468840ad504fef'),
    judul: 'Rumah Kaca',
    penerbit: { nama: 'Bentang Pustaka', kota: 'Yogyakarta' }
  }
]

Hanya Rumah Kaca yang diterbitkan di Yogyakarta. Kedalaman titik bisa berlapis untuk document yang lebih dalam — "alamat.kota.nama" mengikuti struktur selaras. Dot notation juga berlaku untuk array berisi object, dengan satu kekhasan yang akan kita lihat pada bagian array di bawah.

Kesamaan pada Field Array #

Field array punya dua makna pencocokan, dan memahami keduanya menghindarkan kita dari hasil yang mengejutkan. Bentuk pertama: satu nilai biasa dicocokkan terhadap array — document cocok bila salah satu elemen array bernilai itu:

js
db.buku.find({ tag: "sastra" }, { judul: 1, tag: 1 })

Output yang Dihasilkan:

text
[
  {
    _id: ObjectId('6ad3876254468840ad504feb'),
    judul: 'Laut Bercerita',
    tag: [ 'fiksi', 'sastra' ]
  }
]

Laut Bercerita lolos karena "sastra" adalah salah satu elemen tag-nya — elemen lain tidak perlu sama. Bentuk kedua: array lengkap dikirim sebagai nilai — dan di sinilah aturannya berubah menjadi pencocokan array utuh:

js
db.buku.find({ tag: ["fiksi", "remaja"] }, { judul: 1, tag: 1 })

Output yang Dihasilkan:

text
[
  {
    _id: ObjectId('6ad3876254468840ad504fec'),
    judul: 'Bumi',
    tag: [ 'fiksi', 'remaja' ]
  },
  {
    _id: ObjectId('6ad3876254468840ad504fef'),
    judul: 'Rumah Kaca',
    tag: [ 'fiksi', 'remaja' ]
  }
]

Bumi dan Rumah Kaca cocok karena array-nya memang persis ["fiksi", "remaja"]. Sekarang balik urutannya:

js
db.buku.find({ tag: ["remaja", "fiksi"] }).toArray()

Output yang Dihasilkan:

text
[]

Array kosong [] — tidak ada satu document pun yang cocok. Pencocokan array utuh menuntut elemen sama, jumlah sama, dan urutan sama. Laut Bercerita yang punya ["fiksi", "sastra"] pun tidak lolos karena elemennya tidak persis sama.

Sebagai penutup, bersihkan database latihan:

js
db.dropDatabase()

Output yang Dihasilkan:

text
{ ok: 1, dropped: 'latihan_crud' }

Rangkuman #

  • Filter kesamaan ditulis { field: nilai }; pencocokan bersifat exact dan peka huruf besar-kecil.
  • Beberapa pasangan field-nilai dalam satu filter di-AND-kan secara implisit.
  • Field nested dijangkau lewat dot notation seperti "penerbit.kota" — tanda kutip wajib.
  • Nilai biasa terhadap field array mencocokkan salah satu elemen.
  • Nilai array terhadap field array mencocokkan array utuh: elemen, jumlah, dan urutan harus sama persis; gunakan $all untuk niat “punya semua elemen”.

Kesamaan sudah dikuasai. Bab berikutnya melonggarkan tanda sama menjadi perbandingan: lebih dari, kurang dari, dan berada di antara — seluruhnya lewat comparison operators.