MongoDB Academy · Pelajaran

$match dan $project: Menapis dan Membentuk Semula

Pelajar akan meletakkan $match pada peringkat awal saluran paip untuk prestasi dan menggunakan $project untuk menamakan semula serta mengira medan baharu.

Pelajaran 2 daripada 413 langkah

$match dan $project: Menapis dan Membentuk Semula ialah pelajaran MongoDB Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran MongoDB Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus MongoDB Academy merangkumi sejumlah 4 pelajaran.

Tahap $match

Tahap $match ialah padanan setara penapis find() dalam saluran agregasi. Tahap ini menerima sintaks pertanyaan yang sama—semakan kesamaan, operator perbandingan, operator logik, $regex, $elemMatch—dan menapis strim dokumen dengan menggugurkan dokumen yang tidak sepadan. Dokumen yang melepasi penapis bergerak ke tahap seterusnya; dokumen yang tidak sepadan akan dibuang.

// $match uses the same syntax as find() filters
db.orders.aggregate([
  { $match: {
    status: 'completed',
    amount: { $gte: 100 },
    createdAt: { $gte: new Date('2024-01-01') }
  }}
]);
// Only orders matching ALL three conditions pass through

Letakkan $match di Awal untuk Menggunakan Indeks

Apabila $match menjadi tahap pertama dalam saluran, MongoDB boleh menggunakan indeks untuk memenuhi penapis—sama seperti pertanyaan find(). Jika $match muncul selepas tahap lain, kelebihan indeks hilang kerana perancang hanya menolak penggunaan indeks ke tahap pertama. Ini ialah peraturan prestasi yang paling memberi kesan dalam reka bentuk saluran agregasi.

// GOOD: $match first -> uses index on userId
db.orders.aggregate([
  { $match: { userId: 'u1', status: 'active' } },  // index used here
  { $group: { _id: '$productId', count: { $sum: 1 } } }
]);

// BAD: $match after $group -> full collection scan
db.orders.aggregate([
  { $group: { _id: '$productId', count: { $sum: 1 } } },
  { $match: { userId: 'u1' } }  // too late for index
]);

Menggunakan $match Bersama $text

Operator carian teks penuh $text hanya boleh digunakan dalam $match, dan hanya apabila $match ialah tahap pertama saluran. Sekatan ini wujud kerana MongoDB perlu menolak carian teks ke indeks teks, dan perkara itu berlaku pada tahap pelan pertanyaan sebelum sebarang transformasi tahap dilakukan. Selepas $match menapis berdasarkan teks, anda boleh memproyeksikan skor teks dan mengisih mengikut kaitan dalam tahap seterusnya.

db.articles.aggregate([
  // $text in $match MUST be the first stage
  { $match: { $text: { $search: 'mongodb aggregation' } } },
  { $addFields: { score: { $meta: 'textScore' } } },
  { $sort: { score: -1 } },
  { $limit: 5 }
]);

Tahap $project

Tahap $project membentuk semula dokumen: anda boleh menyertakan atau mengecualikan medan, menamakan semula medan dan mengira medan baharu sepenuhnya menggunakan operator ungkapan. Tahap ini menghantar satu dokumen keluaran bagi setiap dokumen masukan (berbeza dengan $group yang menggabungkan banyak dokumen menjadi satu). Tahap $project sering digunakan untuk mengecilkan dokumen sebelum tahap yang mahal, atau untuk menyediakan bentuk keluaran akhir.

db.users.aggregate([
  { $project: {
    _id: 0,             // exclude _id
    name: 1,            // include name
    email: 1,           // include email
    // Exclude password - never send to client!
    // (fields not listed are excluded when any field is included)
  }}
]);

Penyertaan berbanding Pengecualian dalam $project

Seperti unjuran find(), $project tidak boleh mencampurkan penyertaan dan pengecualian dalam tahap yang sama—kecuali _id (yang sentiasa boleh dikecualikan secara jelas walaupun dalam unjuran penyertaan). Tetapkan medan kepada 1 untuk menyertakannya, 0 untuk mengecualikannya, atau gunakan ungkapan untuk mengira dan menyertakannya. Medan yang tidak dinyatakan dalam unjuran penyertaan akan dibuang.

// Inclusion mode: list what you WANT
db.products.aggregate([{
  $project: {
    _id: 0,   // OK to exclude _id in inclusion mode
    name: 1,
    price: 1
  }
}]);

// Exclusion mode: list what you DON'T want
db.products.aggregate([{
  $project: {
    password: 0,
    __v: 0
  }
}]);
// Cannot mix: { name: 1, password: 0 } is an error (except _id)

Mengira Medan Baharu dalam $project

Kekuatan sebenar $project terletak pada pengiraan medan terbitan baharu menggunakan operator ungkapan. Anda boleh menamakan semula medan dengan menetapkannya kepada rujukan medan, melakukan pengiraan aritmetik, memformat rentetan atau menggunakan syarat—semuanya pada sisi pelayan tanpa menyentuh dokumen yang disimpan. Medan yang dikira hanya wujud dalam keluaran saluran; dokumen asas tidak berubah.

db.invoices.aggregate([
  { $project: {
    invoiceNumber: '$_id',         // rename _id to invoiceNumber
    clientName: '$client.name',   // flatten nested field
    subtotal: 1,
    tax: { $multiply: ['$subtotal', 0.08] },        // compute tax
    total: { $add: ['$subtotal', { $multiply: ['$subtotal', 0.08] }] },
    issued: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } }
  }}
]);

Menamakan Semula dan Menyarangkan Medan

Anda boleh menggunakan $project untuk menstruktur semula bentuk dokumen: meratakan medan bersarang ke tahap teratas atau mengumpulkan medan rata ke dalam subdokumen bersarang. Ini berguna untuk menyelaraskan keluaran MongoDB dengan skema respons API yang berbeza daripada struktur dokumen yang disimpan, tanpa mengubah cara anda menyimpan data.

// Document: { firstName: 'Alice', lastName: 'Smith', age: 30 }
// API wants: { name: { first, last }, age }

db.users.aggregate([{
  $project: {
    _id: 0,
    name: {
      first: '$firstName',  // group into nested object
      last: '$lastName'
    },
    age: 1
  }
}]);
// Output: { name: { first: 'Alice', last: 'Smith' }, age: 30 }

Menggunakan $project Bersama Tatasusunan

$project menyokong ungkapan tatasusunan untuk mengubah atau menapis tatasusunan dalam dokumen. Anda boleh menggunakan $map untuk mengubah setiap unsur, $filter untuk memilih unsur yang sepadan dengan syarat, $slice untuk mengambil sebahagian tatasusunan, atau $arrayElemAt untuk mengakses indeks tertentu. Operasi ini berjalan pada sisi pelayan terhadap keseluruhan tatasusunan tanpa memerlukan beberapa tahap saluran.

db.articles.aggregate([{
  $project: {
    title: 1,
    // Keep only published tags
    activeTags: {
      $filter: {
        input: '$tags',
        as: 'tag',
        cond: { $eq: ['$$tag.active', true] }
      }
    },
    // First author only
    leadAuthor: { $arrayElemAt: ['$authors', 0] },
    // Uppercase each tag name
    upperTags: { $map: { input: '$tags', as: 't', in: { $toUpper: '$$t' } } }
  }
}]);

Beberapa Tahap $match

Anda boleh menggunakan beberapa tahap $match dalam saluran yang sama. Corak biasa ialah menggunakan $match pada peringkat awal untuk memanfaatkan indeks, kemudian menggunakan $group atau $project untuk mengira medan baharu, dan selepas itu menggunakan $match kedua untuk menapis berdasarkan nilai yang dikira. $match pertama mendapat manfaat daripada penggunaan indeks; $match kedua menapis set hasil yang telah dikira.

db.orders.aggregate([
  // First $match: uses index on userId
  { $match: { userId: 'u1' } },

  // Compute revenue per product
  { $group: { _id: '$productId', revenue: { $sum: '$amount' } } },

  // Second $match: filter computed revenue (no index possible here)
  { $match: { revenue: { $gte: 500 } } },

  { $sort: { revenue: -1 } }
]);

Bila Hendak Menggunakan $addFields dan Bukan $project

Satu perkara yang sering mengecewakan tentang $project ialah dalam mod penyertaan, anda perlu menyenaraikan setiap medan yang ingin dikekalkan. Jika anda hanya mahu menambah medan baharu tanpa membuang medan sedia ada, gunakan $addFields (atau aliasnya $set). $addFields meneruskan semua medan sedia ada dan hanya menambah atau menggantikan medan yang dinyatakan—jauh lebih ringkas untuk penambahan medan yang dikira.

// $project: must list ALL fields you want to keep
db.users.aggregate([{ $project: { name: 1, email: 1, age: 1,
  ageGroup: { $cond: { if: { $lt: ['$age', 18] }, then: 'minor', else: 'adult' } }
}}]);

// $addFields: keeps all fields, just adds ageGroup
db.users.aggregate([{ $addFields: {
  ageGroup: { $cond: { if: { $lt: ['$age', 18] }, then: 'minor', else: 'adult' } }
}}]);
// All original fields (name, email, age, etc.) are preserved

Prestasi Saluran: Gunakan $project pada Peringkat Awal

Meletakkan tahap $project pada peringkat awal saluran untuk membuang medan yang tidak diperlukan mengurangkan memori dan lebar jalur yang digunakan oleh tahap seterusnya. Jika tahap kemudian tidak memerlukan tatasusunan terbenam yang besar atau medan teks yang panjang, kecualikan medan tersebut dengan $project atau $unset pada peringkat awal. Kesan ini amat ketara apabila dokumen berukuran besar dan saluran mempunyai banyak tahap.

db.articles.aggregate([
  { $match: { status: 'published' } },

  // Trim large fields early before expensive stages
  { $project: {
    title: 1,
    authorId: 1,
    publishedAt: 1,
    categoryId: 1,
    // Exclude: body (could be 50KB), rawHtml (100KB)
    // This reduces memory in all subsequent stages
  }},

  { $lookup: { from: 'authors', localField: 'authorId', foreignField: '_id', as: 'author' } },
  { $sort: { publishedAt: -1 } },
  { $limit: 20 }
]);

Semakan Pantas

Uji pemahaman anda tentang $match dan $project dalam saluran agregasi.

Ulang Kaji Pelajaran

Dalam pelajaran ini, anda telah mempelajari bahawa: $match menapis strim dokumen menggunakan sintaks pertanyaan yang sama seperti find() dan wajar diletakkan pada peringkat pertama untuk memanfaatkan indeks, $project membentuk semula dokumen dengan menyertakan, mengecualikan dan mengira medan, dan $addFields lebih sesuai apabila anda hanya mahu menambah medan tanpa menyenaraikan setiap medan sedia ada. Seterusnya, kita akan membincangkan $group untuk pengagregatan dan pengiraan jumlah.

Percuma untuk bermula

Pelajari JavaScript dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
30
Pelajaran
120

Soalan Lazim

Adakah pelajaran “$match dan $project: Menapis dan Membentuk Semula” percuma?

Ya — teks penuh “$match dan $project: Menapis dan Membentuk Semula” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus MongoDB Academy, tingkat taraf kepada CoddyKit PRO. Kursus MongoDB Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “$match dan $project: Menapis dan Membentuk Semula”?

Pelajar akan meletakkan $match pada peringkat awal saluran paip untuk prestasi dan menggunakan $project untuk menamakan semula serta mengira medan baharu. Anda berlatih MongoDB Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan MongoDB Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran MongoDB Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “$match dan $project: Menapis dan Membentuk Semula” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran MongoDB Academy ini?

Ya. Setiap pelajaran MongoDB Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Konsep Saluran Paip: Peringkat, Operator dan Ungkapan
  2. $match dan $project: Menapis dan Membentuk Semula
  3. $group: Mengagregat dan Mengira Jumlah
  4. $sort, $limit dan $skip dalam Saluran Paip
← Kembali ke MongoDB Academy