MongoDB プロジェクトのネストされたフィールド
- MongoDB プロジェクトのネストされたフィールド
-
MongoDB で
$project
集約ステージを使用してネストされたフィールドをプロジェクトする -
MongoDB で
$unset
集計ステージを使用して指定されたフィールドを除くネストされたフィールドを取得する -
MongoDB で
forEach()
ループを使用してネストされたフィールドを取得する -
MongoDB で
mapReduce()
メソッドを使用してネストされたフィールドをプロジェクトする
今日は、$project
と $unset
の集計ステージ、forEach()
ループ、mapReduce()
メソッドを使用して、MongoDB でデータをクエリしながらネストされたフィールドをプロジェクトする方法を学習します。
MongoDB プロジェクトのネストされたフィールド
MongoDB では、find()
メソッドを使用してすべてのドキュメントを取得できますが、特定のネストされたフィールドにのみアクセスしたい場合はどうでしょうか。ここでプロジェクトを使用します。
ネストされたフィールドはさまざまな方法でプロジェクトできます。ここでは、ネストされたフィールドをプロジェクトするための次のソリューションについて学習します。
$project
集計ステージを使用します$unset
集計ステージを使用しますforEach()
ループを使用しますmapReduce()
関数を使用します
上記のアプローチを学ぶために、1つのドキュメントを含む nested
という名前のコレクションを作成しましょう。また、以下のクエリを使用してフォローアップすることもできます。
サンプルコード:
// MongoDB version 5.0.8
> db.nested.insertOne(
{
"name": {
"first_name": "Mehvish",
"last_name": "Ashiq",
},
"contact": {
"phone":{"type": "manager", "number": "123456"},
"email":{ "type": "office", "mail": "delfstack@example.com"}
},
"country_name" : "Australien",
"posting_locations" : [
{
"city_id" : 19398,
"city_name" : "Bondi Beach (Sydney)"
},
{
"city_id" : 31101,
"city_name" : "Rushcutters Bay (Sydney)"
},
{
"city_id" : 31022,
"city_name" : "Wolly Creek (Sydney)"
}
],
"regions" : {
"region_id" : 796,
"region_name" : "Australien: New South Wales (Sydney)"
}
}
);
db.nested.find().pretty();
を使用します挿入されたデータを確認するには、mongo シェルで。
MongoDB で $project
集約ステージを使用してネストされたフィールドをプロジェクトする
サンプルコード:
// MongoDB version 5.0.8
> var current_location = "posting_locations";
> var project = {};
> project["id"] = "$"+current_location+".city_id";
> project["name"] = "$"+current_location+".city_name";
> project["regions"] = 1;
> var find = {};
> find[current_location] = {"$exists":true};
> db.nested.aggregate([
{ $match : find },
{ $project : project }
]).pretty()
出力:
{
"_id" : ObjectId("62a96d397c7e3688aea26d0d"),
"regions" : {
"region_id" : 796,
"region_name" : "Australien: New South Wales (Sydney)"
},
"id" : [
19398,
31101,
31022
],
"name" : [
"Bondi Beach (Sydney)",
"Rushcutters Bay (Sydney)",
"Wolly Creek (Sydney)"
]
}
ここでは、posting_locations
という名前の第 1 レベルのフィールドを current_location
という変数に保存します。
次に、その変数を使用して city_id
と city_name
にアクセスし、ブラケット表記を使用して project
オブジェクトのプロパティを作成しながら、それらを project
オブジェクトに保存します。さらに、project["regions"]
の regions
フィールドを保存します。
次に、aggregate()
メソッドでドキュメントを照合するために使用する find
という名前の別のオブジェクトがあります。aggregate()
メソッドでは、$match
ステージを使用してドキュメントを照合し、$project
を使用してネストされているか最初のレベルであるかに関係なくフィールドをプロジェクトします。
$project
を使用して、出力に表示するフィールドを指定します。フィルタクエリを使用せずに、指定されたネストされたフィールドのみをプロジェクトする場合は、次のソリューションを使用できます。
サンプルコード:
// MongoDB version 5.0.8
> var current_location = "posting_locations";
> db.nested.aggregate({
$project: {
"_id": 0,
"city_id": "$" + current_location + ".city_id",
"city_name": "$" + current_location + ".city_name",
"regions": 1
}
}).pretty();
出力:
{
"regions" : {
"region_id" : 796,
"region_name" : "Australien: New South Wales (Sydney)"
},
"city_id" : [
19398,
31101,
31022
],
"city_name" : [
"Bondi Beach (Sydney)",
"Rushcutters Bay (Sydney)",
"Wolly Creek (Sydney)"
]
}
MongoDB で $unset
集計ステージを使用して指定されたフィールドを除くネストされたフィールドを取得する
サンプルコード:
// MongoDB version 5.0.8
> db.nested.aggregate({
$unset: ["posting_locations.city_id", "contact", "regions", "name", "_id"]
}).pretty()
出力:
{
"country_name" : "Australien",
"posting_locations" : [
{
"city_name" : "Bondi Beach (Sydney)"
},
{
"city_name": "Rushcutters Bay (Sydney)"
},
{
"city_name": "Wolly Creek (Sydney)"
}
]
}
ここでは、$unset
演算子を使用します。この演算子は、指定されたフィールドまたはフィールドの配列を削除するために使用されます。
埋め込みドキュメントまたはドキュメントの配列を指定するためにドット表記を使用することを忘れないでください。指定されたフィールドが存在しない場合、$unset
演算子は操作を実行しません。
$
を使用して配列の要素を照合する場合、$unset
演算子は、一致する要素を配列から削除するのではなく、null
に置き換えます。この動作は、要素の位置と配列サイズの一貫性を維持するのに役立ちます。
MongoDB で forEach()
ループを使用してネストされたフィールドを取得する
サンプルコード:
// MongoDB version 5.0.8
> var bulk = db.newcollection.initializeUnorderedBulkOp(),
counter = 0;
> db.nested.find().forEach(function(doc) {
var document = {};
document["name"] = doc.name.first_name + " " + doc.name.last_name;
document["phone"] = doc.contact.phone.number;
document["mail"] = doc.contact.email.mail;
bulk.insert(document);
counter++;
if (counter % 1000 == 0) {
bulk.execute();
bulk = db.newcollection.initializeUnorderedBulkOp();
}
});
> if (counter % 1000 != 0) { bulk.execute(); }
次のようなものが表示されます。
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 1,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
次に、mongo シェルで以下のコマンドを実行して、プロジェクトされたフィールドを確認します。
// MongoDB version 5.0.8
> db.newcollection.find().pretty();
出力:
{
"_id" : ObjectId("62a96f2d7c7e3688aea26d0e"),
"name" : "Mehvish Ashiq",
"phone" : "123456",
"mail" : "delfstack@example.com"
}
このサンプルコードを学習するために、特定のネストされたフィールドを取得して、それらを新しいコレクションに挿入するとします。ここで、変換されたフィールドをドキュメントとして新しいコレクションに挿入すると、ネストされたコレクションのサイズに基づいて操作に影響を与える可能性があります。
新しい順序付けされていない一括挿入
API を使用することで、この遅い挿入パフォーマンスを回避できます。一括送信することで挿入操作を合理化し、操作が成功したか失敗したかについてリアルタイムでフィードバックを提供します。
そのため、bulk insert
API を使用して、目的のデータ構造を newcollection
コレクションに挿入します。ここで、新しいドキュメントは、nested
コレクションカーソルの forEach()
ループで作成されます。新しいプロパティを作成するには、括弧表記を使用します。
このコードでは、大量のデータがあると想定しています。そのため、一括挿入操作を実行するために、1000
のバッチでサーバーに操作を送信します。
その結果、各リクエストを送信するのではなく、サーバーへの 1000 リクエストごとに 1 回だけ送信するため、優れたパフォーマンスが得られます。
MongoDB で mapReduce()
メソッドを使用してネストされたフィールドをプロジェクトする
サンプルコード:
// MongoDB version 5.0.8
> function map() {
for(var i in this.posting_locations) {
emit({
"country_id" : this.country_id,
"city_id" : this.posting_locations[i].city_id,
"region_id" : this.regions.region_id
},1);
}
}
> function reduce(id,docs) {
return Array.sum(docs);
}
> db.nested.mapReduce(map,reduce,{ out : "map_reduce_output" } )
次に、次のクエリを実行して出力を確認します。
// MongoDB version 5.0.8
> db.map_reduce_output.find().pretty();
出力:
{
"_id" : {
"country_id" : undefined,
"city_id" : 19398,
"region_id" : 796
},
"value" : 1
}
{
"_id" : {
"country_id" : undefined,
"city_id" : 31022,
"region_id" : 796
},
"value" : 1
}
{
"_id" : {
"country_id" : undefined,
"city_id" : 31101,
"region_id" : 796
},
"value" : 1
}
このサンプルコードでは、mapReduce()
関数を使用して、nested
コレクションのすべてのドキュメントに対して map-reduce を実行します。そのためには、以下に簡単に説明する 3つのステップのプロセスに従う必要があります。
-
すべての入力ドキュメントを処理するための
map()
関数を定義します。この関数では、this
キーワードは map-reduce 操作によって処理されている現在のドキュメントを参照し、emit()
関数は指定された値をキーにマップして返します。 -
ここでは、対応する
reduce()
関数を定義します。これは、データの集約が行われる実際の場所です。2つの引数(キー
と値
)を取ります。このコード例では、id
とdocs
を使用しています。docs
の要素は、map()
メソッドからemit()
関数によって返されることに注意してください。このステップで、reduce()
関数はdocs
配列をその値(要素)の合計に減らします。 -
最後に、
map()
およびreduce()
関数を使用して、nested
コレクション内のすべてのドキュメントに対して map-reduce を実行します。out
を使用して、指定されたコレクション(この場合はmap_reduce_output
)に出力を保存します。