MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

MongoDBの$project演算子でフィールドを射影(プロジェクション)する方法

MongoDBの集計パイプライン(aggregation pipeline)において、ドキュメントから特定のフィールドを射影(プロジェクション)して出力形式を整形したい場合は、$project ステージを使用します。$project を使うと、表示するフィールドの選択だけでなく、$cond$ifNull などの演算子を組み合わせて、条件に応じた値の変換や代替値の設定も可能です。

この記事では、実際にコレクションを作成し、$project を使ってネストされたフィールドを条件付きで射影する方法を解説します。

1. サンプルコレクションの作成

まず、insertOne() メソッドを使って、ドキュメントを含むコレクションを作成します。ここでは学生の名前と点数情報を持つ3件のドキュメントを挿入します。なお、3件目のドキュメントは意図的に異なるフィールド名(Score1、Score2)を使用しています。

> db.demo439.insertOne(
...     {
...        "Name" : "Chris",
...        "MarksInformation" : {
...           "Marks1" : 67,
...           "Marks2" : 45,
...           "Marks3" : 78
...        }
...     }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e77833abbc41e36cc3caeab")
}
> db.demo439.insertOne(
...     {
...        "Name" : "David",
...        "MarksInformation" : {
...           "Marks1" : 50,
...           "Marks2" : 57,
...           "Marks3" : 68
...        }
...     }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e77833abbc41e36cc3caeac")
}
> db.demo439.insertOne(
...     {
...        "Name" : "Bob",
...        "MarksInformation" : {
...           "Score1" : 65,
...           "Score2" : 71
...        }
...     }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e77833bbbc41e36cc3caead")
}

2. find()メソッドですべてのドキュメントを表示

find() メソッドを使って、コレクション内のすべてのドキュメントを表示します。

> db.demo439.find();

このクエリを実行すると、次のような出力が得られます。

{ "_id" : ObjectId("5e77833abbc41e36cc3caeab"), "Name" : "Chris", "MarksInformation" : { "Marks1" : 67, "Marks2" : 45, "Marks3" : 78 } }
{ "_id" : ObjectId("5e77833abbc41e36cc3caeac"), "Name" : "David", "MarksInformation" : { "Marks1" : 50, "Marks2" : 57, "Marks3" : 68 } }
{ "_id" : ObjectId("5e77833bbbc41e36cc3caead"), "Name" : "Bob", "MarksInformation" : { "Score1" : 65, "Score2" : 71 } }

3. $projectでフィールドを射影するクエリ

続いて、$project を使用してフィールドを射影するクエリを見ていきましょう。ポイントは以下の通りです。

  • $ifNull: フィールドが存在しない場合やnullの場合に、代わりのデフォルト値(ここでは0)を返します。
  • $eq: 値が等しいかどうかを比較します。ここでは「Marks1が0(=存在しない)かどうか」を判定しています。
  • $cond: 条件分岐を行います。条件がtrueなら第2引数の値、falseなら第3引数の値を返します。

つまり、「Marks1」フィールドが存在しない場合は「Score1」の値を代わりに使い、存在する場合はそのまま「Marks1」の値を出力する、という処理を実現しています。

> db.demo439.aggregate({
...    $project: {
...       "Name" : 1,
...       "Marks1": { $cond: [ { $eq:[ { $ifNull: [ "$MarksInformation.Marks1", 0 ] }, 0 ] }, { $ifNull: [ "$MarksInformation.Score1", 0 ] }, "$MarksInformation.Marks1" ] },
...       "Marks2": { $cond: [ { $eq:[ { $ifNull: [ "$MarksInformation.Marks2", 0 ] }, 0 ] }, { $ifNull: [ "$MarksInformation.Score2", 0 ] }, "$MarksInformation.Marks2" ] },
...       "Marks3": { $cond: [ { $eq:[ { $ifNull: [ "$MarksInformation.Marks3", 0] }, 0 ] }, { $ifNull: [ "$MarksInformation.Score3", 0 ] }, "$MarksInformation.Marks3" ] }
... }})

4. 実行結果

上記の集計クエリを実行すると、次のような出力が得られます。

{ "_id" : ObjectId("5e77833abbc41e36cc3caeab"), "Name" : "Chris", "Marks1" : 67, "Marks2" : 45, "Marks3" : 78 }
{ "_id" : ObjectId("5e77833abbc41e36cc3caeac"), "Name" : "David", "Marks1" : 50, "Marks2" : 57, "Marks3" : 68 }
{ "_id" : ObjectId("5e77833bbbc41e36cc3caead"), "Name" : "Bob", "Marks1" : 65, "Marks2" : 71, "Marks3" : 0 }

結果のポイント

出力結果に注目すると、Bobのドキュメントには元々「Marks1」「Marks2」というフィールドが存在せず、「Score1」「Score2」のみが存在していました。しかし、$project の条件付き射影によって、Score1とScore2の値(65と71)がそれぞれMarks1とMarks2として出力されています。また、Marks3もScore3も存在しないため、デフォルト値の0が出力されています。

このように$project$cond$ifNull$eq と組み合わせることで、スキーマが不統一なドキュメントでも、出力形式を統一した整形済みデータとして取得できます。フィールド名が揺れているデータセットを扱う際に非常に便利なテクニックなので、ぜひ活用してみてください。

  1. MongoDBで特定のフィールドを条件にドキュメントを検索する方法($or演算子の使い方)

    MongoDBでは、複数のフィールドにまたがる条件を指定してドキュメントを検索できます。本記事では、$or 演算子を使って「名前(Name)」または「国名(CountryName)」のいずれかに一致するドキュメントを取得する方法を、実際のコード例とともに解説します。1. コレクションの作成とドキュメントの挿入まず、insertOne() メソッドを使用してサンプル用のコレクションを作成し、ドキュメントを挿入します。> db.demo371.insertOne({Name:David,CountryName:US}); { acknowledged : true, insert

  2. MongoDBの_idフィールドを非表示にする方法

    MongoDBの_idフィールドを非表示にする方法MongoDBでは、find()メソッドでドキュメントを検索すると、デフォルトで_idフィールド(ObjectId)が必ず結果に含まれます。しかし、射影(プロジェクション)という仕組みを使えば、この_idフィールドを非表示にし、必要なフィールドだけを取得することが可能です。本記事では、具体的な手順をサンプルコード付きで解説します。1. コレクションとドキュメントの作成まず、サンプル用のコレクションを作成し、ドキュメントを挿入します。> db.demo575.insertOne({id:101, Information:{Name:&quo