【MongoDB】範囲条件で埋め込みドキュメントの配列をクエリする方法
埋め込みドキュメント(サブドキュメント)の配列を範囲条件で絞り込んで取得したい場合は、aggregate()メソッドと集計パイプラインを使用するのが効果的です。この記事では、実際にコレクションを作成し、配列内の各要素を指定した数値の範囲でフィルタリングする手順を解説します。
1. サンプルコレクションの作成
まずは、ユーザー情報を埋め込みドキュメントの配列として持つコレクションを作成しましょう。
> db.demo346.insertOne(
... {
... _id: 101,
... userDetails: [
... { UserName: "Chris", Score:78},
... { UserName: "David", Score:68},
... { UserName: "Bob", Score:88}
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : 101 }
> db.demo346.insertOne(
... {
... _id: 102,
... userDetails: [
... { UserName: "Mike", Score:92},
... { UserName: "Sam", Score:62},
... { UserName: "Carol", Score:97}
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : 102 }
2. 登録データの確認
find()メソッドを使って、コレクション内のすべてのドキュメントを表示してみます。
> db.demo346.find();
上記のコマンドを実行すると、次のような出力が得られます。
{
"_id" : 101, "userDetails" : [
{ "UserName" : "Chris", "Score" : 78 },
{ "UserName" : "David", "Score" : 68 },
{ "UserName" : "Bob", "Score" : 88 }
]
}
{
"_id" : 102, "userDetails" : [
{ "UserName" : "Mike", "Score" : 92 },
{ "UserName" : "Sam", "Score" : 62 },
{ "UserName" : "Carol", "Score" : 97 }
]
}
3. 範囲条件で配列内の埋め込みドキュメントをフィルタリングする
ここからが本題です。以下のように aggregate() を使うことで、「Score が 80 以上 99 以下」という範囲条件に一致する要素だけを配列内に残すことができます。
> db.demo346.aggregate([
... { "$match": { "$expr": { "$gte": [{ "$size": { "$ifNull": ["$userDetails", []] } }, 1] }}},
... { "$addFields": {
... "userDetails": {
... "$filter": {
... "input": { "$ifNull": ["$userDetails", []] },
... "cond": {
... "$and": [
... { "$gte": ["$$this.Score", 80] },
... { "$lte": ["$$this.Score", 99] }
... ]
... }
... }
... }
... }}
... ])
パイプラインのポイント
- $match ステージ:$expr と $size を組み合わせることで、userDetails フィールドが存在し、かつ少なくとも1件の要素を持つドキュメントだけを対象にしています。$ifNull を併用すれば、フィールドが存在しないドキュメントでもエラーにならず、空の配列として安全に処理されます。
- $addFields + $filter ステージ:既存の userDetails 配列を、cond で指定した条件($$this.Score が 80〜99 の範囲内)を満たす要素だけで置き換えます。$$this は、現在処理中の配列要素そのものを参照する変数です。
4. 実行結果
パイプラインを実行すると、範囲条件に一致する要素のみが残った次の結果が得られます。
{ "_id" : 101, "userDetails" : [ { "UserName" : "Bob", "Score" : 88 } ] }
{ "_id" : 102, "userDetails" : [ { "UserName" : "Mike", "Score" : 92 }, { "UserName" : "Carol", "Score" : 97 } ] }
_id: 101 のドキュメントでは Bob(88点)のみ、_id: 102 のドキュメントでは Mike(92点)と Carol(97点)だけが残っていることが分かります。このように $filter を活用すれば、配列ごと取得するのではなく、配列内の特定の条件を満たす埋め込みドキュメントだけを柔軟に抽出できるため、スコアや日付などの範囲検索に非常に便利です。
-
MongoDBのaggregate()で3階層にネストされた埋め込みドキュメントの配列をフィルタリングする方法
MongoDBでネストされた配列をフィルタリングする基本アプローチMongoDBで3階層にネストされた埋め込みドキュメントの配列をフィルタリングするには、aggregate()メソッドを使用します。集計パイプラインの中で$unwindによって配列を展開し、$matchで条件に一致するドキュメントを絞り込むのが基本的な流れです。この記事では、実際のコード例を通じて具体的な手順を解説します。1. サンプルコレクションの作成まずは動作確認用のコレクションを作成し、ドキュメントを挿入してみましょう。> db.demo736.insertOne( ... { ... _id:
-
MongoDBでオブジェクト配列内の特定のネストされたドキュメントをクエリする方法
MongoDBでオブジェクトの配列からネストされたドキュメントを抽出する オブジェクトの配列に格納されたネストされたドキュメントを条件付きで検索したい場合、find()メソッドに$elemMatch演算子を組み合わせることで、指定した条件に一致する要素だけを取り出すことができます。 ここでは、「StudentAge」フィールドを持つ学生情報だけを配列から抽出する例を見ていきましょう。 1. サンプルコレクションの作成 まず、ドキュメントを挿入してコレクションを作成します。このコレクションには、学生情報がオブジェクトの配列として格納されています。 > db.demo763.insertO