MongoDB 配列の操作

MongoDBBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、MongoDB の配列の扱い方を学びます。配列は MongoDB における基本的なデータ構造であり、単一のドキュメント内に値のリストを格納することができます。配列フィールドを持つドキュメントの作成、要素の追加と削除、配列内の値の更新、配列の内容に基づいたクエリの実行など、さまざまな操作を探索します。これらのスキルは、MongoDB で複雑なデータ構造を効果的に管理するために不可欠です。

この実験(Lab)を終える頃には、MongoDB の配列の扱い方について確固たる実践的な理解を得ることができ、より洗練された柔軟なデータベーススキーマを構築できるようになります。

配列フィールドを持つドキュメントの作成

最初のステップでは、MongoDB サーバーに接続し、配列フィールドを含む新しいドキュメントを作成します。配列は、タグ、コメント、コースなど、複数の関連する値をドキュメント内に直接格納できるため強力です。

まず、MongoDB シェルを開いてデータベースとの対話を開始します。この実験(Lab)の以降のすべての操作は、この mongosh シェル内で行います。

mongosh

シェルに入ると、test> のようなプロンプトが表示されます。この実験(Lab)のために事前に設定された arraylab データベースに切り替えましょう。

use arraylab

setup スクリプトは既に students コレクションを作成し、1 つのドキュメントを挿入しています。「Alice Johnson」という名前の学生の新しいドキュメントを挿入します。このドキュメントには、文字列の配列である courses フィールドが含まれます。

db.students.insertOne({
    name: "Alice Johnson",
    age: 22,
    courses: ["Mathematics", "Computer Science", "Physics"]
})

このコマンドは、students コレクションに 1 つのドキュメントを挿入します。courses フィールドは、3 つの文字列要素を含む配列を保持します。

ドキュメントが正常に作成されたことを確認するには、find() メソッドを使用してコレクション内のすべてのドキュメントを取得できます。.pretty() メソッドは、出力をより読みやすくフォーマットします。

db.students.find().pretty()

セットアップ中に作成された「Bob Smith」のドキュメントと、先ほど追加した「Alice Johnson」のドキュメントの 2 つのドキュメントが表示されるはずです。

[
  {
    _id: ObjectId("..."),
    name: 'Bob Smith',
    grades: [ 95, 87, 92 ],
    activities: [ 'Chess Club', 'Debate Team' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Alice Johnson',
    age: 22,
    courses: [ 'Mathematics', 'Computer Science', 'Physics' ]
  }
]

配列に要素を追加する

配列を作成した後、一般的なタスクは新しい要素を追加することです。このステップでは、既存の配列に要素を追加するために $push 演算子を使用する方法を学びます。

配列に単一の要素を追加するには、更新操作で $push 演算子を使用します。Alice Johnson のコースリストに新しいコース「Data Science」を追加しましょう。

db.students.updateOne(
    { name: "Alice Johnson" },
    { $push: { courses: "Data Science" } }
)

このコマンドでは、最初の引数 { name: "Alice Johnson" } は更新するドキュメントを見つけるためのフィルターです。2 番目の引数 { $push: { courses: "Data Science" } } は更新アクションを指定します。$push は値「Data Science」を courses 配列に追加します。

Alice のドキュメントを再度検索して変更を確認しましょう。

db.students.find({ name: "Alice Johnson" }).pretty()

出力には、配列に追加された新しいコースが表示されます。

[
  {
    _id: ObjectId("..."),
    name: 'Alice Johnson',
    age: 22,
    courses: [ 'Mathematics', 'Computer Science', 'Physics', 'Data Science' ]
  }
]

一度に複数の要素を追加するには、$push$each 修飾子を組み合わせることができます。Bob Smith のために 2 つの新しいアクティビティを追加しましょう。

db.students.updateOne(
    { name: "Bob Smith" },
    { $push: { activities: { $each: ["Robotics Club", "Swimming Team"] } } }
)

ここでは、$each$push に対して、提供されたリスト(["Robotics Club", "Swimming Team"])の各項目を activities 配列に追加するように指示します。

この更新も確認しましょう。

db.students.find({ name: "Bob Smith" }).pretty()

出力は、両方の新しいアクティビティが追加されたことを確認します。

[
  {
    _id: ObjectId("..."),
    name: 'Bob Smith',
    grades: [ 95, 87, 92 ],
    activities: [ 'Chess Club', 'Debate Team', 'Robotics Club', 'Swimming Team' ]
  }
]

配列から要素を削除する

要素を追加できるのと同様に、削除することも必要です。MongoDB はこの目的のためにいくつかの演算子を提供しています。このステップでは、値で要素を削除するために $pull を、位置で要素を削除するために $pop を使用する方法を学びます。

値に基づいて配列から特定の要素を削除するには、$pull 演算子を使用します。Alice のコースリストから「Physics」を削除しましょう。

db.students.updateOne(
    { name: "Alice Johnson" },
    { $pull: { courses: "Physics" } }
)

このコマンドは Alice のドキュメントを見つけ、彼女の courses 配列から「Physics」のすべての出現箇所を削除します。結果を確認しましょう。

db.students.find({ name: "Alice Johnson" }).pretty()

出力には、「Physics」が配列に含まれていないことが示されています。

[
  {
    _id: ObjectId("..."),
    name: 'Alice Johnson',
    age: 22,
    courses: [ 'Mathematics', 'Computer Science', 'Data Science' ]
  }
]

リスト内の値に一致する複数の要素を削除するには、$pullAll 演算子を使用できます。Bob のアクティビティから「Chess Club」と「Debate Team」の両方を削除しましょう。

db.students.updateOne(
    { name: "Bob Smith" },
    { $pullAll: { activities: ["Chess Club", "Debate Team"] } }
)

Bob のドキュメントの更新を確認しましょう。

db.students.find({ name: "Bob Smith" }).pretty()

出力は、指定されたアクティビティの削除を確認します。

[
  {
    _id: ObjectId("..."),
    name: 'Bob Smith',
    grades: [ 95, 87, 92 ],
    activities: [ 'Robotics Club', 'Swimming Team' ]
  }
]

配列の先頭または末尾から要素を削除する必要がある場合は、$pop 演算子を使用できます。最後の要素を削除するには 1 を、最初の要素を削除するには -1 を使用します。Alice のリストから最後のコースを削除しましょう。

db.students.updateOne(
    { name: "Alice Johnson" },
    { $pop: { courses: 1 } }
)

Alice のコースの最終状態を見てみましょう。

db.students.find({ name: "Alice Johnson" }).pretty()

出力には、最後の要素である「Data Science」が削除されたことが示されています。

[
  {
    _id: ObjectId("..."),
    name: 'Alice Johnson',
    age: 22,
    courses: [ 'Mathematics', 'Computer Science' ]
  }
]

配列の要素を更新する

配列内の既存の要素を更新することは、もう一つの重要な操作です。このステップでは、位置指定演算子を使用して配列要素を更新する方法を説明します。

配列内の特定の単一要素を更新するには、まずドキュメントと変更したい要素を一致させる必要があります。その後、位置指定演算子 $ を使用して更新を実行できます。Alice の courses 配列で「Mathematics」を「Advanced Mathematics」に変更しましょう。

db.students.updateOne(
    { name: "Alice Johnson", courses: "Mathematics" },
    { $set: { "courses.$": "Advanced Mathematics" } }
)

このコマンドでは、フィルター { name: "Alice Johnson", courses: "Mathematics" } がドキュメントを見つけ、配列内の「Mathematics」の最初の出現位置を特定します。更新 { $set: { "courses.$": "Advanced Mathematics" } } は、courses.$ を使用してその一致した要素の位置を参照し、新しい値を設定します。

変更を確認しましょう。

db.students.find({ name: "Alice Johnson" }).pretty()

出力には、更新されたコース名が表示されます。

[
  {
    _id: ObjectId("..."),
    name: 'Alice Johnson',
    age: 22,
    courses: [ 'Advanced Mathematics', 'Computer Science' ]
  }
]

条件に一致する配列内のすべての要素を更新するには、すべて位置指定演算子 $[ ] を使用できます。$inc (インクリメント) 演算子を使用して、Bob のすべての成績を 5 ポイント増やしましょう。

db.students.updateOne(
    { name: "Bob Smith" },
    { $inc: { "grades.$[]": 5 } }
)

ここでは、grades.$[]grades 配列のすべての要素に $inc 操作を適用します。

Bob の新しい成績を確認しましょう。

db.students.find({ name: "Bob Smith" }).pretty()

出力には、各成績が 5 ポイント増加したことが示されています。

[
  {
    _id: ObjectId("..."),
    name: 'Bob Smith',
    grades: [ 100, 92, 97 ],
    activities: [ 'Robotics Club', 'Swimming Team' ]
  }
]

配列の内容に基づいてドキュメントをクエリする

クエリはあらゆるデータベースの中心です。MongoDB は、配列の内容に基づいてドキュメントをクエリするための豊富な演算子を提供しています。この最後のステップでは、配列要素とそのプロパティを一致させることによってドキュメントを見つける方法を学びます。

配列に特定の要素が含まれているすべてのドキュメントを見つけるには、クエリフィルターにその値を含めることができます。「Computer Science」に登録されているすべての学生を見つけましょう。

db.students.find({ courses: "Computer Science" }).pretty()

このクエリは、Alice の courses 配列に「Computer Science」が含まれているため、Alice のドキュメントを返します。

配列に指定された要素のセットの すべて が含まれているドキュメントを見つけるには、$all 演算子を使用します。

db.students.find({
    courses: { $all: ["Advanced Mathematics", "Computer Science"] }
}).pretty()

このクエリも Alice のドキュメントを返します。なぜなら、彼女の courses 配列にはこれら両方の値が含まれているからです。

配列要素に対するより複雑な条件については、$elemMatch 演算子が非常に役立ちます。これにより、単一の配列要素が満たす必要がある複数の基準を指定できます。95 より大きい成績を少なくとも 1 つ持っている学生を見つけましょう。

db.students.find({
    grades: { $elemMatch: { $gt: 95 } }
}).pretty()

このクエリは Bob のドキュメントを返します。なぜなら、彼は現在 95 を超える成績を持っているからです。$gt は「greater than」(より大きい)を表します。

$size 演算子を使用して、配列内の要素数に基づいてクエリすることもできます。ちょうど 2 つのアクティビティに参加している学生を見つけましょう。

db.students.find({
    activities: { $size: 2 }
}).pretty()

このクエリは Bob のドキュメントを返します。なぜなら、彼の activities 配列には現在 2 つの要素が含まれているからです。

最後に、複合クエリの練習のために学生をもう一人追加しましょう。

db.students.insertOne({
    name: "Charlie Brown",
    courses: ["Art", "Music", "Literature"],
    grades: [88, 92, 85],
    activities: ["Painting Club"]
})

次に、「Art」または「Music」のいずれかを受講しており($in 演算子を使用)、かつ 90 以上の成績を少なくとも 1 つ持っている($elemMatch$gte を使用)学生を見つけます。

db.students.find({
    courses: { $in: ["Art", "Music"] },
    grades: { $elemMatch: { $gte: 90 } }
}).pretty()

このクエリは、「Charlie Brown」のドキュメントを返します。彼は両方の条件を満たしています。

まとめ

この実験では、MongoDB で配列を扱うための基本的なテクニックを学びました。まず配列フィールドを持つドキュメントを作成し、次に $push$each を使用して要素を追加する練習をしました。値による要素の削除を $pull$pullAll で、位置による削除を $pop で行いました。また、位置指定演算子 $ を使用して特定の配列要素を更新する方法と、$[ ] 演算子を使用してすべての要素を更新する方法も学びました。最後に、$all$elemMatch$size$in などの演算子を使用して配列の内容に基づいてドキュメントをクエリする練習をしました。これらのスキルは、MongoDB で複雑なネストされたデータ構造を持つアプリケーションを構築および管理するために不可欠です。