Judul buku, nama penulis, dan kategori adalah string — dan tampilan akhirnya hampir selalu butuh polesan: judul dan penulis digabung dalam satu baris, harga angka berprefiks Rp, spasi berlebih dibuang, dan URL toko membutuhkan slug seperti atomic-habits. Operator string di aggregation mengerjakan semua itu sebagai expression di dalam pipeline, tanpa memutar data lewat kode aplikasi. Chapter ini merangkai, membersihkan, memotong, dan mencocokkan teks dari katalog toko buku.

Peta materi Chapter ini:

  • Merangkai dan mengubah kapital: $concat, $toUpper, $toLower, $toString.
  • Membersihkan dan memotong: $trim, $split, $strLenCP, $substrCP.
  • Mencocokkan dan mengganti pola: $regexMatch, $replaceOne, $replaceAll.

Peta Operator #

OperatorPeran
$concatmerangkai beberapa string menjadi satu
$toUpper / $toLowermengubah ke kapital semua / huruf kecil semua
$toStringmengonversi nilai (angka, tanggal, boolean) menjadi string
$trim / $ltrim / $rtrimmembuang spasi dua sisi / kiri saja / kanan saja
$splitmemecah string menjadi array dengan pemisah
$strLenCPpanjang string dalam satuan code point
$substrCPpotongan string berdasarkan code point
$regexMatchmenguji pola regular expression, hasil boolean
$replaceOne / $replaceAllmengganti kemunculan pertama / semua kemunculan

Siapkan data uji standar Section ini:

js
use latihan_agregasi2
db.dropDatabase()
db.buku.insertMany([
  { judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, kategori: "fiksi", terjual: 120, tanggal_terbit: ISODate("2017-02-01T00:00:00Z"), tag: ["fiksi", "sastra", "penghargaan"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Siti", bintang: 4 } ] },
  { judul: "Bumi", penulis: "Tere Liye", harga: 89000, kategori: "fiksi", terjual: 250, tanggal_terbit: ISODate("2014-09-02T00:00:00Z"), tag: ["fiksi", "remaja", "fantasi"], ulasan: [ { pengulas: "Dewi", bintang: 5 }, { pengulas: "Budi", bintang: 4 }, { pengulas: "Siti", bintang: 5 } ] },
  { judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, kategori: "nonfiksi", terjual: 180, tanggal_terbit: ISODate("2018-07-01T00:00:00Z"), tag: ["filsafat", "pengembangan diri"], ulasan: [ { pengulas: "Siti", bintang: 5 } ] },
  { judul: "Atomic Habits", penulis: "James Clear", harga: 115000, kategori: "nonfiksi", terjual: 310, tanggal_terbit: ISODate("2018-10-16T00:00:00Z"), tag: ["pengembangan diri", "terjemahan"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Dewi", bintang: 4 } ] },
  { judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, kategori: "fiksi", terjual: 120, tanggal_terbit: ISODate("2016-06-15T00:00:00Z"), tag: ["fiksi", "remaja"], ulasan: [ { pengulas: "Dewi", bintang: 4 } ] },
  { judul: "Bumi Manusia", penulis: "Pramoedya A. Toer", harga: 105000, kategori: "sastra", terjual: 150, tanggal_terbit: ISODate("1980-05-25T00:00:00Z"), tag: ["sastra", "sejarah"], ulasan: [ { pengulas: "Budi", bintang: 5 }, { pengulas: "Siti", bintang: 5 }, { pengulas: "Dewi", bintang: 4 } ] },
  { judul: "Hujan Bulan Juni", penulis: "Sapardi Djoko Damono", harga: 65000, kategori: "puisi", terjual: 75, tanggal_terbit: ISODate("1994-06-10T00:00:00Z"), tag: ["puisi", "sastra"] },
  { judul: "Ensiklopedia Sains Populer", penulis: "Tim Sains", harga: 250000, kategori: "referensi", terjual: 40, tanggal_terbit: ISODate("2020-03-05T00:00:00Z"), tag: ["referensi", "sains"], ulasan: [ { pengulas: "Dewi", bintang: 4 } ] }
])

Output yang Dihasilkan:

text
switched to db latihan_agregasi2
{ ok: 1, dropped: 'latihan_agregasi2' }
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('6ad3a6b0ea5f5ad5636b7255'),
    '1': ObjectId('6ad3a6b0ea5f5ad5636b7256'),
    '2': ObjectId('6ad3a6b0ea5f5ad5636b7257'),
    '3': ObjectId('6ad3a6b0ea5f5ad5636b7258'),
    '4': ObjectId('6ad3a6b0ea5f5ad5636b7259'),
    '5': ObjectId('6ad3a6b0ea5f5ad5636b725a'),
    '6': ObjectId('6ad3a6b0ea5f5ad5636b725b'),
    '7': ObjectId('6ad3a6b0ea5f5ad5636b725c')
  }
}

Merangkai dan Mengubah Kapital #

Empat operator pembuka dipakai sekaligus pada satu buku:

js
db.buku.aggregate([
  { $match: { judul: "Filosofi Teras" } },
  { $project: { _id: 0,
      judulPenulis: { $concat: ["$judul", " — ", "$penulis"] },
      judulKapital: { $toUpper: "$judul" },
      penulisKecil: { $toLower: "$penulis" },
      hargaTeks: { $concat: ["Rp", { $toString: "$harga" }] } } }
])

Output yang Dihasilkan:

text
[
  {
    judulPenulis: 'Filosofi Teras — Henry Manampiring',
    judulKapital: 'FILOSOFI TERAS',
    penulisKecil: 'henry manampiring',
    hargaTeks: 'Rp89000'
  }
]

$concat menerima daftar string dan merangkainya berurutan — pemisah seperti " — " harus ikut ditulis eksplisit. $toUpper dan $toLower mengubah kapital seluruh string. Satu jebakan umum: $concat menolak angka, sehingga harga (89000) wajib dikonversi dulu dengan $toString — hasilnya "Rp89000". Untuk angka bernilai pecahan atau format ribuan, konversi lebih baik dilakukan di sisi aplikasi.

Membersihkan dan Memotong #

Data dari form atau berkas lama sering datang dengan spasi berlebih. $trim membuang spasi (dan tab/newline) di kedua ujung; $ltrim dan $rtrim mengerjakannya satu sisi. Di bawah ini spasi sengaja disuntikkan lewat $concat agar efek pembersihannya terlihat:

js
db.buku.aggregate([
  { $match: { judul: "Filosofi Teras" } },
  { $project: { _id: 0, judul: 1,
      bersih: { $trim: { input: { $concat: ["  ", "$judul", "  "] } } },
      namaDepan: { $arrayElemAt: [ { $split: ["$penulis", " "] }, 0 ] },
      panjangJudul: { $strLenCP: "$judul" },
      potonganJudul: { $substrCP: ["$judul", 0, 8] } } }
])

Output yang Dihasilkan:

text
[
  {
    judul: 'Filosofi Teras',
    bersih: 'Filosofi Teras',
    namaDepan: 'Henry',
    panjangJudul: 14,
    potonganJudul: 'Filosofi'
  }
]

$trim mengembalikan teks tanpa empat spasi suntikan. $split memecah "Henry Manampiring" menjadi ["Henry", "Manampiring"], lalu $arrayElemAt dari Chapter Operator Array mengambil element pertamanya sebagai namaDepan. $strLenCP menghitung 14 karakter, dan $substrCP memotong 8 code point pertama menjadi "Filosofi".

Mencocokkan dan Mengganti: $regexMatch, $replaceOne, $replaceAll #

$regexMatch mengembalikan true/false — cocok untuk flag di laporan. $replaceOne mengganti kemunculan pertama, $replaceAll seluruh kemunculan. Ketiganya dipadukan untuk membuat slug URL:

js
db.buku.aggregate([
  { $match: { judul: "Atomic Habits" } },
  { $project: { _id: 0, judul: 1, penulis: 1,
      cocokHabits: { $regexMatch: { input: "$judul", regex: /habits/i } },
      singkatPenulis: { $replaceOne: { input: "$penulis", find: "Clear", replacement: "C." } },
      slug: { $replaceAll: { input: { $toLower: "$judul" }, find: " ", replacement: "-" } } } }
])

Output yang Dihasilkan:

text
[
  {
    judul: 'Atomic Habits',
    penulis: 'James Clear',
    cocokHabits: true,
    singkatPenulis: 'James C.',
    slug: 'atomic-habits'
  }
]

Tiga hal terjadi: pola /habits/i mencocokkan “Habits” tanpa peduli kapital berkat opsi i — alternatifnya menulis regex: "habits", options: "i"; $replaceOne mengubah "James Clear" menjadi "James C."; dan $replaceAll mengganti setiap spasi pada judul huruf-kecil dengan tanda hubung, menghasilkan slug atomic-habits. Terapkan pada seluruh katalog, slug itu siap dipakai sebagai URL:

js
db.buku.aggregate([
  { $project: { _id: 0, judul: 1,
      slug: { $replaceAll: { input: { $toLower: "$judul" }, find: " ", replacement: "-" } } } },
  { $sort: { judul: 1 } }
])

Output yang Dihasilkan:

text
[
  { judul: 'Atomic Habits', slug: 'atomic-habits' },
  { judul: 'Bumi', slug: 'bumi' },
  { judul: 'Bumi Manusia', slug: 'bumi-manusia' },
  {
    judul: 'Ensiklopedia Sains Populer',
    slug: 'ensiklopedia-sains-populer'
  },
  { judul: 'Filosofi Teras', slug: 'filosofi-teras' },
  { judul: 'Hujan Bulan Juni', slug: 'hujan-bulan-juni' },
  { judul: 'Laut Bercerita', slug: 'laut-bercerita' },
  { judul: 'Rumah Kaca', slug: 'rumah-kaca' }
]

Delapan judul berubah menjadi delapan slug rapi. Perhatikan bahwa Ensiklopedia Sains Populer menjadi ensiklopedia-sains-populer — kedua spasi terganti karena $replaceAll menyapu semua kemunculan, bukan hanya yang pertama.

Rangkuman #

  • $concat merangkai string (angka wajib lewat $toString); $toUpper/$toLower mengubah kapital.
  • $trim/$ltrim/$rtrim membersihkan spasi ujung; $split memecah string jadi array; $strLenCP dan $substrCP menghitung dan memotong per code point.
  • $regexMatch menguji pola (dukung options: "i"), $replaceOne/$replaceAll mengganti teks — kombinasinya membangun slug URL.
  • Semuanya expression: tempatnya di $project, $set, atau di dalam expression lain.

String terformat, label siap tampil. Chapter berikutnya kembali ke angka: operator aritmetika untuk menghitung pendapatan, diskon, pembulatan, hingga selisih tanggal.