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

$project(集計)

項目一覧

  • 定義
  • 互換性
  • 構文
  • 動作
  • Considerations
$project

リクエストされたフィールドを含むドキュメントをパイプラインの次のステージに渡します。指定するフィールドは、入力ドキュメントの既存フィールドであっても新規に計算されるフィールドであっても構いません。

次の環境でホストされる配置には $project を使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

$projectステージのプロトタイプ形式は次のとおりです。

{ $project: { <specification(s)> } }

$project が受け入れるドキュメントでは、含めるフィールド、非表示にする _id フィールド、新たに加えるフィールド、値をリセットする既存フィールドの指定が可能です。除外するフィールドを指定することもできます。

$project の指定形式は次のとおりです。

フォーム
説明

<field>: <1 or true>

フィールドを含めるかどうかを指定します。ゼロ以外の整数も true として扱われます。

_id: <0 or false>

_id フィールドで非表示にする項目を指定します。

条件付きでフィールドを除外するには、代わりにREMOVE 変数を使用します。詳細については、「 条件付きでのフィールドの除外 」を参照してください。

<field>: <expression>

新規フィールドを追加するか、既存フィールドの値をリセットします。

式が$$REMOVE と評価された場合、フィールドは出力から除外されます。詳細については、「 条件付きでのフィールドの除外 」を参照してください。

<field>: <0 or false>

フィールドの除外を指定します。

条件付きでフィールドを除外するには、代わりにREMOVE 変数を使用します。詳細については、「 条件付きでのフィールドの除外 」を参照してください。

_id以外のフィールドを除外するよう指定した場合、他の$project 指定形式は採用できません。この制限は、REMOVE 変数を使用したフィールドの条件付き除外には適用されません。

フィールドを除外するには、「$unset」ステージも参照してください。

  • _id フィールドはデフォルトで出力ドキュメントに含まれます。入力ドキュメントの他のフィールドを出力ドキュメントに含めるには、$project で明示的に含めるフィールドを指定する必要があります。

  • 含めるフィールドとしてドキュメントにないものを指定すると、$project はその指定を無視し、ドキュメントにそのフィールドを追加しません。

_id フィールドはデフォルトで出力ドキュメントに含まれます。出力ドキュメントから _id フィールドを除外するには、$project_id フィールドの非表示を指定します。

1 つまたは複数のフィールドを除外するように指定すると、他のすべてのフィールドが出力ドキュメントに返されます。

{ $project: { "<field1>": 0, "<field2>": 0, ... } } // Return all but the specified fields

_id 以外のフィールドを除外するよう指定した場合、$project の他の指定形式は採用できません。つまり、フィールドを除外する場合、含めるフィールドの指定、既存フィールド値のリセット、新規フィールドの追加のいずれの操作もできません。この制限は、REMOVE 変数を使用したフィールドの条件付き除外には適用されません。

フィールドを除外するには、「$unset」ステージも参照してください。

集計式で変数 REMOVE を使用して、条件付きでフィールドを非表示にできます。使用例については、「条件付きでのフィールドの除外」を参照してください。

注意

MongoDB には、ドキュメントに新しいフィールドを追加するための $addFields も用意されています。

新しいフィールドを追加したり、既存フィールドの値をリセットしたりするには、フィールド名を指定して、その値を何らかの式に設定します。式の詳細については、「式演算子」を参照してください。

フィールドの値をリテラルに解決される式ではなく、数値やブール値のリテラルに直接設定する場合は、$literal 演算子を使用しますそれ以外の場合、$project は数値またはブール値のリテラルを、フィールドを含めるまたは除外するためのフラグとして扱います。

新規フィールドを指定し、既存フィールドのフィールドパスに値を設定すると、フィールド名を実質的に変更できます。

$project ステージでは、角括弧 [] を使用して新しい配列フィールドを直接作成できます。ドキュメントに存在しない配列フィールドを指定した場合にこの操作を実行すると、その配列フィールドの値は null に置き換わります。使用例については、「プロジェクトの新しい配列フィールド」を参照してください。

$project ステージでは配列インデックスを使用できません。詳細については、「配列インデックスの非対応」を参照してください。

埋め込みドキュメント内のフィールドをプロジェクションするか追加/リセットする場合、次の例のようにドット表記を使用できます。

"contact.address.country": <1 or 0 or expression>

または、フィールドをネストできます。

contact: { address: { country: <1 or 0 or expression> } }

フィールドをネストする場合、次例のとおり、フィールドを指定するために埋め込みドキュメント内でドット表記を使用することはできませんcontact: { "address.country": <1 or 0 or expression> }無効です。

埋め込みドキュメントとその埋め込みドキュメント内のフィールドの両方を同じプロジェクションで指定することはできません。

次の $project ステージは、埋め込み contact ドキュメントと contact.address.country フィールドの両方をプロジェクトしようとするため、Path collision エラーで失敗します。

{ $project: { contact: 1, "contact.address.country": 1 } }

親ドキュメントと埋め込みフィールドの指定順序にかかわらず、エラーが発生します。次の $project は、同じエラーで失敗します。

{ $project: { "contact.address.country": 1, contact: 1 } }

$project ステージを使用する場合、通常このステージをパイプラインの最後のステージにして、クライアントに返すフィールドを指定するために使用します。

パイプラインの最初や途中に $project ステージを使用して、その後のパイプラインステージに渡されるフィールドの数を減らすことは、パフォーマンスの向上にはつながりません。なぜなら、データベースはこの最適化を自動的に行うからです。

MongoDB は、$project ステージが空のドキュメントとして渡される場合、エラーを返します。

たとえば、次のパイプラインを実行するとエラーが発生します。

db.myCollection.aggregate( [ {
$project: { }
} ] )

$project ステージでは配列インデックスを使用できません。詳細については、「配列インデックスの非対応」を参照してください。

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}

次の $project ステージでは、_id フィールド、title フィールド、author フィールドのみが出力ドキュメントに含まれます。

db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )

この操作の結果、次のドキュメントが作成されます。

{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

_id フィールドは常時含まれるようにデフォルト設定されています。$project ステージの出力ドキュメントから _id フィールドを除外するには、プロジェクション ドキュメントで _id フィールドを 0 に設定してこのフィールドの除外を指定します。

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}

次の $project ステージでは _id フィールドは出力ドキュメントから除外されていますが、title フィールドと author フィールドは出力ドキュメントに含まれています。

db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )

この操作の結果、次のドキュメントが作成されます。

{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}

次の $project ステージでは、lastModified フィールドが出力から除外されます。

db.books.aggregate( [ { $project : { "lastModified": 0 } } ] )

フィールドを除外するには、「$unset」ステージも参照してください。

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}

次の $project ステージでは、author.first フィールドと lastModified フィールドが出力から除外されます。

db.books.aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )

あるいは、除外指定をドキュメント内にネストすることもできます。

db.bookmarks.aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )

どちらを指定しても出力結果は同じになります。

{
"_id" : 1,
"title" : "abc123",
"isbn" : "0001122223334",
"author" : {
"last" : "zzz"
},
"copies" : 5,
}

フィールドを除外するには、「$unset」ステージも参照してください。

集計式で変数 REMOVE を使用して、条件付きでフィールドを非表示にできます。

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}
{
"_id" : 2,
title: "Baked Goods",
isbn: "9999999999999",
author: { last: "xyz", first: "abc", middle: "" },
copies: 2,
lastModified: "2017-07-21"
}
{
"_id" : 3,
title: "Ice Cream Cakes",
isbn: "8888888888888",
author: { last: "xyz", first: "abc", middle: "mmm" },
copies: 5,
lastModified: "2017-07-22"
}

次の $project ステージでは、author.middle フィールドが "" と等しい場合に限り、REMOVE 変数を使用してそのフィールドを除外します。

db.books.aggregate( [
{
$project: {
title: 1,
"author.first": 1,
"author.last" : 1,
"author.middle": {
$cond: {
if: { $eq: [ "", "$author.middle" ] },
then: "$$REMOVE",
else: "$author.middle"
}
}
}
}
] )

集計操作の結果、次の出力が得られます。

{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
{ "_id" : 2, "title" : "Baked Goods", "author" : { "last" : "xyz", "first" : "abc" } }
{ "_id" : 3, "title" : "Ice Cream Cakes", "author" : { "last" : "xyz", "first" : "abc", "middle" : "mmm" } }

Tip

$addFields との比較

ドキュメントフィールドを削除するには、$addFields または $project ステージを使用できます。最適なアプローチは、パイプラインと、元のドキュメントをどれだけ保持するかによって異なります。

$addFieldsステージで $$REMOVE を使用する例については、「フィールドの削除」を参照してください。

以下のドキュメントを持つbookmarksコレクションを考えてみましょう。

{ _id: 1, user: "1234", stop: { title: "book1", author: "xyz", page: 32 } }
{ _id: 2, user: "7890", stop: [ { title: "book2", author: "abc", page: 5 }, { title: "book3", author: "ijk", page: 100 } ] }

埋め込みドキュメントの title フィールドのみを stop フィールドに含めるには、ドット表記を使用できます。

db.bookmarks.aggregate( [ { $project: { "stop.title": 1 } } ] )

または、ドキュメント内に含める指定をネストすることもできます。

db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )

どちらを指定しても結果は次のドキュメントになります。

{ "_id" : 1, "stop" : { "title" : "book1" } }
{ "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }

次の文書を持つbooksコレクションを考えます。

{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}

次の $project ステージは、新フィールドの isbnlastNamecopiesSold を追加します。

db.books.aggregate(
[
{
$project: {
title: 1,
isbn: {
prefix: { $substr: [ "$isbn", 0, 3 ] },
group: { $substr: [ "$isbn", 3, 2 ] },
publisher: { $substr: [ "$isbn", 5, 4 ] },
title: { $substr: [ "$isbn", 9, 3 ] },
checkDigit: { $substr: [ "$isbn", 12, 1] }
},
lastName: "$author.last",
copiesSold: "$copies"
}
}
]
)

この操作の結果、次のドキュメントが作成されます。

{
"_id" : 1,
"title" : "abc123",
"isbn" : {
"prefix" : "000",
"group" : "11",
"publisher" : "2222",
"title" : "333",
"checkDigit" : "4"
},
"lastName" : "zzz",
"copiesSold" : 5
}

たとえば、コレクションに次のドキュメントが含まれているとします。

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }

次の操作では、x フィールドと y フィールドを新規フィールドである myArray の要素としてプロジェクションします。

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )

この操作を実行すると次のドキュメントが返されます。

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }

配列の指定にドキュメント内に存在しないフィールドが含まれている場合、この操作ではそのフィールドの値として null が置き換えられます。

たとえば、上記と同じドキュメントで次の操作を実行すると、x フィールドと y フィールド、および存在しない $someField フィールドが新規フィールドである myArray の要素としてプロジェクションされます。

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )

この操作を実行すると次のドキュメントが返されます。

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }

$project ステージでは配列インデックスを使用できません。このセクションで一例を挙げます。

次の pizzas コレクションを作成します。

db.pizzas.insert( [
{ _id: 0, name: [ 'Pepperoni' ] },
] )

次の例ではピザが返されます。

db.pizzas.aggregate( [
{ $project: { x: '$name', _id: 0 } },
] )

出力例ではピザが返されます。

[ { x: [ 'Pepperoni' ] } ]

次の例では、配列インデックス($name.0)を使用してピザを返そうと試みています。

db.pizzas.aggregate( [
{ $project: { x: '$name.0', _id: 0 } },
] )

出力例では、ピザは返されません。

[ { x: [] } ]

戻る

$planCacheStats