Docs Menu
Docs Home
/
MongoDBマニュアル
/ / /

$replaceWith(集計)

項目一覧

  • 定義
  • 動作
$replaceWith

入力ドキュメントを指定したドキュメントで置き換えます。この操作により、_id フィールドを含む入力ドキュメント内の既存のフィールドがすべて置き換えられます。$replaceWithを使用すると、埋め込みドキュメントを最上位に引き上げます。新しいドキュメントを代わりとして指定することもできます。

$replaceWithステージは $replaceRootステージと同じアクションを実行しますが、ステージの形式は異なります。

$replaceWith ステージの形式は次のとおりです。

{ $replaceWith: <replacementDocument> }

置換用ドキュメントには、有効なに変換される任意のドキュメントが利用できます。 式の詳細については、「式 」を参照してください。

<replacementDocument>がドキュメントでない場合、 $replaceWithはエラーとなり失敗します。

<replacementDocument> が欠損ドキュメント(つまり、ドキュメントが存在しない)に変換される場合、$replaceWith はエラーとなり失敗します。たとえば、次のドキュメントを含むコレクションを作成します。

db.collection.insertMany([
{ "_id": 1, "name" : { "first" : "John", "last" : "Backus" } },
{ "_id": 2, "name" : { "first" : "John", "last" : "McCarthy" } },
{ "_id": 3, "name": { "first" : "Grace", "last" : "Hopper" } },
{ "_id": 4, "firstname": "Ole-Johan", "lastname" : "Dahl" },
])

次に、ドキュメントの 1 つに name フィールドがないため、以下の $replaceWith 操作は失敗します。

db.collection.aggregate([
{ $replaceWith: "$name" }
])

エラーを回避するには、$mergeObjects を使用して name ドキュメントをデフォルトのドキュメントと結合します。次に例を示します。

db.collection.aggregate([
{ $replaceWith: { $mergeObjects: [ { _id: "$_id", first: "", last: "" }, "$name" ] } }
])

あるいは、ドキュメントを$replaceWith ステージに渡す前にドキュメント フィールドの存在を確認する $match ステージを含めることで、name フィールドがないドキュメントをスキップすることもできます。

db.collection.aggregate([
{ $match: { name : { $exists: true, $not: { $type: "array" }, $type: "object" } } },
{ $replaceWith: "$name" }
])

または、$ifNull 式を使用して、次に挙げるような他のドキュメントをルートに指定しても構いません。

db.collection.aggregate([
{ $replaceWith: { $ifNull: [ "$name", { _id: "$_id", missingName: true} ] } }
])

次のドキュメントを含むpeopleという名前のコレクションを作成します。

db.people.insertMany([
{ "_id" : 1, "name" : "Arlene", "age" : 34, "pets" : { "dogs" : 2, "cats" : 1 } },
{ "_id" : 2, "name" : "Sam", "age" : 41, "pets" : { "cats" : 1, "fish" : 3 } },
{ "_id" : 3, "name" : "Maria", "age" : 25 }
])

次の操作では、$replaceWith ステージを使用して、各入力ドキュメントを $mergeObjects 操作の結果に置き換えます。$mergeObjects 式は、指定のデフォルト ドキュメントを pets ドキュメントとマージします。

db.people.aggregate( [
{ $replaceWith: { $mergeObjects: [ { dogs: 0, cats: 0, birds: 0, fish: 0 }, "$pets" ] } }
] )

この操作は次の結果を返します。

{ "dogs" : 2, "cats" : 1, "birds" : 0, "fish" : 0 }
{ "dogs" : 0, "cats" : 1, "birds" : 0, "fish" : 3 }
{ "dogs" : 0, "cats" : 0, "birds" : 0, "fish" : 0 }

students という名前のコレクションには次のドキュメントが含まれています。

db.students.insertMany([
{
"_id" : 1,
"grades" : [
{ "test": 1, "grade" : 80, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 85, "mean" : 90, "std" : 4 },
{ "test": 3, "grade" : 95, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "test": 1, "grade" : 90, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 87, "mean" : 90, "std" : 3 },
{ "test": 3, "grade" : 91, "mean" : 85, "std" : 4 }
]
}
])

次の操作では、90 以上の grade フィールドを持つ埋め込みドキュメントが最上位レベルに引き上げられます。

db.students.aggregate( [
{ $unwind: "$grades" },
{ $match: { "grades.grade" : { $gte: 90 } } },
{ $replaceWith: "$grades" }
] )

この操作は次の結果を返します。

{ "test" : 3, "grade" : 95, "mean" : 85, "std" : 6 }
{ "test" : 1, "grade" : 90, "mean" : 75, "std" : 6 }
{ "test" : 3, "grade" : 91, "mean" : 85, "std" : 4 }

サンプルコレクション sales には、次のドキュメントが入力されています。

db.sales.insertMany([
{ "_id" : 1, "item" : "butter", "price" : 10, "quantity": 2, date: ISODate("2019-03-01T08:00:00Z"), status: "C" },
{ "_id" : 2, "item" : "cream", "price" : 20, "quantity": 1, date: ISODate("2019-03-01T09:00:00Z"), status: "A" },
{ "_id" : 3, "item" : "jam", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" },
{ "_id" : 4, "item" : "muffins", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" }
])

レポート作成の目的で、完了した販売ごとに、現在のレポート実行時点の合計金額を計算するとします。次の操作は、ステータスが C のすべての販売を検索し、$replaceWith ステージを使用して新しいドキュメントを作成します。$replaceWith は合計金額を計算し、変数 NOW を使用して現在の時刻を取得します。

db.sales.aggregate([
{ $match: { status: "C" } },
{ $replaceWith: { _id: "$_id", item: "$item", amount: { $multiply: [ "$price", "$quantity"]}, status: "Complete", asofDate: "$$NOW" } }
])

この操作により、次のドキュメントが返されます。

{ "_id" : 1, "item" : "butter", "amount" : 20, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 3, "item" : "jam", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 4, "item" : "muffins", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }

サンプルコレクション reportedsales には、四半期および地域ごとに報告された売上情報が入力されています。

db.reportedsales.insertMany( [
{ _id: 1, quarter: "2019Q1", region: "A", qty: 400 },
{ _id: 2, quarter: "2019Q1", region: "B", qty: 550 },
{ _id: 3, quarter: "2019Q1", region: "C", qty: 1000 },
{ _id: 4, quarter: "2019Q2", region: "A", qty: 660 },
{ _id: 5, quarter: "2019Q2", region: "B", qty: 500 },
{ _id: 6, quarter: "2019Q2", region: "C", qty: 1200 }
] )

レポート作成の目的で、四半期ごとに報告された売上データを表示したいとします。例を以下に示します。

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

四半期ごとにグループ化されたデータを表示するには、次の集計パイプラインを使用できます。

db.reportedsales.aggregate( [
{ $addFields: { obj: { k: "$region", v: "$qty" } } },
{ $group: { _id: "$quarter", items: { $push: "$obj" } } },
{ $project: { items2: { $concatArrays: [ [ { "k": "_id", "v": "$_id" } ], "$items" ] } } },
{ $replaceWith: { $arrayToObject: "$items2" } }
] )
第 1 ステージ:

$addFields ステージでは、キー k を地域値として定義し、値 v をその地域の数量として定義する新しい obj ドキュメント フィールドが追加されます。以下に例を挙げます。

{ "_id" : 1, "quarter" : "2019Q1", "region" : "A", "qty" : 400, "obj" : { "k" : "A", "v" : 400 } }
第 2 ステージ:

$group ステージは四半期ごとにグループ化され、$push を使用して obj フィールドを新しい items 配列フィールドに累積します。以下に例を挙げます。

{ "_id" : "2019Q1", "items" : [ { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
第 3 ステージ:

$projectステージでは、$concatArraysを使用して、_id 情報と items 配列の要素を含む新しい配列 items2 を作成します。

{ "_id" : "2019Q1", "items2" : [ { "k" : "_id", "v" : "2019Q1" }, { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
第 4 ステージ

$replaceWithは、 $arrayToObjectを使用してitems2をドキュメントに変換し、指定されたキーkと値vのペアを使用して、そのドキュメントを次のステージに出力します。 例:

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

この集計により、次のドキュメントが返されます。

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
{ "_id" : "2019Q2", "A" : 660, "B" : 500, "C" : 1200 }

次のドキュメントを含むcontactsという名前のコレクションを作成します。

db.contacts.insertMany( [
{ "_id" : 1, name: "Fred", email: "fred@example.net" },
{ "_id" : 2, name: "Frank N. Stine", cell: "012-345-9999" },
{ "_id" : 3, name: "Gren Dell", cell: "987-654-3210", email: "beo@example.net" }
] )

次の操作では、 $replaceWith$mergeObjectsを使用して、欠落しているフィールドのデフォルト値を持つ現在のドキュメントを出力します。

db.contacts.aggregate( [
{ $replaceWith:
{ $mergeObjects:
[
{ _id: "", name: "", email: "", cell: "", home: "" },
"$$ROOT"
]
}
}
] )

この集計は、次のドキュメントを返します。

{
_id: 1,
name: 'Fred',
email: 'fred@example.net',
cell: '',
home: ''
},
{
_id: 2,
name: 'Frank N. Stine',
email: '',
cell: '012-345-9999',
home: ''
},
{
_id: 3,
name: 'Gren Dell',
email: 'beo@example.net',
cell: '',
home: '987-654-3210'
}

戻る

$replaceRoot

項目一覧