パイプラインの概念:ステージ、演算子、式
データがパイプラインの各ステージを通過する仕組みを理解し、ステージ演算子と式演算子を区別します。
「パイプラインの概念:ステージ、演算子、式」はCoddyKit上の無料MongoDB Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはMongoDB Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 MongoDB Academyコースには全4レッスンが含まれています。
集計パイプラインとは
集計パイプラインは、MongoDBのサーバーサイドデータ変換エンジンです。生のドキュメントを取得してアプリケーションコードで処理する代わりに、データストリームを段階的に変換するステージの順序を定義します。フィルタリング、形状変更、グループ化、計算、並べ替えをすべてデータベースエンジン内で実行できます。これにより、負荷の高い計算をデータの近くで行い、ネットワーク経由で送信するデータ量を大幅に減らせます。
// A simple aggregation pipeline
db.orders.aggregate([
{ $match: { status: 'completed' } }, // stage 1: filter
{ $group: { _id: '$userId', total: { $sum: '$amount' } } }, // stage 2: group
{ $sort: { total: -1 } }, // stage 3: sort
{ $limit: 10 } // stage 4: take top 10
]);ドキュメントがステージを通過する仕組み
パイプラインをベルトコンベアのように考えてみましょう。各ドキュメントはステージ1に入り、変換(または除外)された後、結果がステージ2、ステージ3へと順に流れていきます。各ステージで、ドキュメントの集合は縮小(フィルタリング)したり、拡大(unwind)したり、計算された集計結果に完全に置き換えられたりします。フィルター条件を満たさないドキュメントはパイプラインから除外され、後続のステージに到達することはありません。
// Data flow visualization:
// Input: 10,000 orders
// Stage 1 ($match: status='completed'): 8,000 docs
// Stage 2 ($group by userId): 1,200 docs (one per user)
// Stage 3 ($sort by total DESC): 1,200 docs (reordered)
// Stage 4 ($limit 10): 10 docs
// Output to client: 10 docsステージ演算子と式演算子
集計フレームワークでは、2種類の演算子を区別します。ステージ演算子($が先頭に付く)は、$match、$group、$projectのようにパイプラインステージの処理内容を定義します。一方、式演算子(こちらも$が先頭に付く)は、$sum、$avg、$concatのようにステージ内で値を計算します。ステージが処理の構成要素であり、式はその内部で行う計算です。
db.sales.aggregate([
// $group is a STAGE operator
{ $group: {
_id: '$region',
// $sum and $avg are EXPRESSION operators (accumulators here)
totalRevenue: { $sum: '$amount' },
avgOrder: { $avg: '$amount' },
// $concat is an expression operator
label: { $concat: ['Region: ', '$region'] }
}}
]);$記号を使用したフィールド参照
集計式の中で$が先頭に付いた文字列はフィールド参照であり、現在のドキュメントにあるそのフィールドの値を参照します。接頭辞がない文字列はリテラル値として扱われます。この違いは非常に重要です。'$price'は「priceフィールドの値」を意味しますが、'price'はリテラル文字列「price」を意味します。
db.products.aggregate([
{ $project: {
name: 1,
// '$price' references the 'price' field value
discountedPrice: { $multiply: ['$price', 0.9] },
// 'price' without $ is a literal string
label: 'price', // all docs get the string 'price', not the field value
// $$ROOT is a special variable for the whole document
original: '$$ROOT'
}}
]);システム変数: $$ROOT、$$NOW、$$CURRENT
集計パイプラインには、$$が先頭に付いたシステム変数が用意されており、特殊な値にアクセスできます。$$ROOTは現在のドキュメント全体を参照し、$$NOWは現在の日時を表します($projectで計算フィールドを作成する場合に便利です)。$$CURRENTは現在のドキュメントのフィールドパスコンテキストを表し、$$REMOVEは値として割り当てると条件付きでフィールドを削除します。
db.orders.aggregate([
{ $project: {
_id: 1,
orderDate: 1,
daysOld: {
$divide: [
{ $subtract: ['$$NOW', '$orderDate'] }, // $$NOW = current time
1000 * 60 * 60 * 24 // convert ms to days
]
},
// Conditionally remove a field:
sensitiveField: { $cond: { if: '$isAdmin', then: '$secret', else: '$$REMOVE' } }
}}
]);主要なパイプラインステージの概要
MongoDBには数十種類のパイプラインステージがあります。特に重要なのは、$match(ドキュメントをフィルタリング)、$project(フィールドの形状変更・計算)、$group(キーごとの集計)、$sort(結果の並べ替え)、$limitと$skip(ページネーション)、$lookup(別のコレクションとの結合)、$unwind(配列のフラット化)です。これらを使いこなせば、ほぼあらゆる分析クエリを表現できます。
// Quick reference of the most-used stages:
// $match - { $match: { field: condition } }
// $project - { $project: { keep: 1, drop: 0, computed: expr } }
// $group - { $group: { _id: '$field', agg: { $sum: '$val' } } }
// $sort - { $sort: { field: 1 or -1 } }
// $limit - { $limit: N }
// $skip - { $skip: N }
// $lookup - { $lookup: { from, localField, foreignField, as } }
// $unwind - { $unwind: '$arrayField' }パイプラインの最適化: ステージの順序が重要
MongoDBのクエリオプティマイザーは、効率化のために一部のパイプラインステージを自動的に並べ替えます。たとえば可能な場合は、$matchを$sortや$groupより前に移動します。ただし、自分で$matchを常にできるだけ早い段階に配置してください$matchが最初のステージであれば、MongoDBはインデックスを使用できます。
// BAD: expensive group before filter
db.orders.aggregate([
{ $group: { _id: '$userId', total: { $sum: '$amount' } } },
{ $match: { total: { $gt: 1000 } } } // too late to use index
]);
// GOOD: filter first, then group
db.orders.aggregate([
{ $match: { status: 'completed', createdAt: { $gte: thisYear } } },
{ $group: { _id: '$userId', total: { $sum: '$amount' } } },
{ $match: { total: { $gt: 1000 } } }
]);算術式演算子
算術式を使うと、ステージ内の既存のフィールドから新しい値を計算できます。特によく使われるものは、$add、$subtract、$multiply、$divide、$mod、$absです。これらの演算子は、フィールド参照、リテラル、または他の式の結果に対して使用できるため、これまでアプリケーション側で処理する必要があった複雑な計算も実行できます。
db.invoices.aggregate([
{ $project: {
subtotal: '$subtotal',
taxAmount: { $multiply: ['$subtotal', 0.08] }, // 8% tax
total: { $add: ['$subtotal', { $multiply: ['$subtotal', 0.08] }] },
discount: { $subtract: ['$listPrice', '$salePrice'] },
margin: { $divide: [{ $subtract: ['$price', '$cost'] }, '$price'] }
}}
]);条件式: $cond と $ifNull
条件式を使うと、集計ステージ内でif/else ロジックを記述できます。$condはブール式を評価し、2つの値のいずれかを返します(3項演算子に相当します)。$ifNullは、フィールドがnullまたは存在しない場合に代替値を返します。これらは、任意フィールドを処理したり、保存されたデータを変更せずに派生カテゴリを計算したりするために不可欠です。
db.products.aggregate([
{ $project: {
name: 1,
price: 1,
// Ternary: label products as budget or premium
tier: {
$cond: {
if: { $lt: ['$price', 100] },
then: 'budget',
else: 'premium'
}
},
// Fallback for missing description
description: { $ifNull: ['$description', 'No description available'] }
}}
]);文字列式演算子
文字列演算子を使うと、パイプライン内でテキストフィールドを操作できます。$concatは文字列を連結し、$toUpper/$toLowerは大文字と小文字を変換し、$trim/$ltrim/$rtrimは空白を削除し、$substrは部分文字列を抽出し、$splitは区切り文字で分割します。これらは、保存されたドキュメントを更新せずに、集計中にデータを正規化する場合に役立ちます。
db.users.aggregate([
{ $project: {
// Combine first and last name
fullName: { $concat: ['$firstName', ' ', '$lastName'] },
// Normalise email to lowercase
emailNorm: { $toLower: '$email' },
// Extract domain from email
domain: {
$arrayElemAt: [{ $split: ['$email', '@'] }, 1]
}
}}
]);日付式演算子
日付演算子は、グループ化や計算のために日付フィールドから各要素を抽出します。$year、$month、$dayOfMonth、$hour、$minute、$dayOfWeek、$dateToStringなどがあります。これらは、「月ごとの注文総数」や「曜日ごとの平均売上」のような時系列分析に不可欠です。
// Group orders by year and month
db.orders.aggregate([
{ $group: {
_id: {
year: { $year: '$createdAt' },
month: { $month: '$createdAt' }
},
count: { $sum: 1 },
revenue: { $sum: '$amount' }
}},
{ $sort: { '_id.year': 1, '_id.month': 1 } }
]);理解度チェック
このレッスンで学んだ集計パイプラインの概念について、理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、パイプラインステージがドキュメントのストリームを順番に変換すること、ステージ演算子がステージの処理内容を定義する一方で、式演算子がステージ内の値を計算すること、そして$がフィールド参照の前置詞、$$がシステム変数の前置詞であることを学びました。次は、フィルターと形状変更の中心となる$matchと$projectに焦点を当てます。
AI チューターと学ぶ JavaScript — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 30
- レッスン
- 120
よくある質問
「パイプラインの概念:ステージ、演算子、式」レッスンは無料ですか?
はい。「パイプラインの概念:ステージ、演算子、式」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、MongoDB Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 MongoDB Academyコースには全4レッスンが含まれています。
「パイプラインの概念:ステージ、演算子、式」で何を学びますか?
データがパイプラインの各ステージを通過する仕組みを理解し、ステージ演算子と式演算子を区別します。 ブラウザで直接実行するハンズオンコードでMongoDB Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
MongoDB Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのMongoDB Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「パイプラインの概念:ステージ、演算子、式」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このMongoDB Academyレッスンでコードを書いて実行できますか?
はい。すべてのMongoDB Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- パイプラインの概念:ステージ、演算子、式
- $matchと$project:フィルターと形状変更
- $group:集約と合計値の計算
- パイプラインでの$sort、$limit、$skip