ELW株式会社 テックブログ

リアルなログをそのままお届けします。

RDB脳のためのMongoDB覚書

◆用語

コレクション

RDBのテーブルに相当。RDBの場合は同テーブルであれば必ず同スキーマだが、コレクションでは同スキーマである必要はなく、異なるフィールドを混在させることが可能。

ドキュメント

RDBのレコードに相当。フィールドと値のペアのBSON(JSONをバイナリでエンコードしたデータ形式)で保持される。フィールドに対しインデックスを作成することも可能。

e.g. usersコレクションのドキュメントイメージ

{
  _id: ObjectId("607c72ef1f1f7f3d5b08d7a9"),
  name: "User One",
  email: "user1@example.com",
  age: 28
}
{
  _id: ObjectId("507f191e810c19729de860ea"),
  name: "User Two",
  email: "user2@example.com",
  age: 32,
  note: "sample text"
}

また、JSON Schema Validationを用いることでフィールドにデータ型(string, int, etc...)を指定することもできる。

◆接続

MongoDBに接続すると、データベース名を明示的に指定しない場合、デフォルトでtestデータベースが使用される。異なるデータベースを使用したい場合はuseコマンドを使用する。

use users

この時、まだ存在していないデータベース名を指定することで新規作成されるが、最低1つのコレクションがないと実体化されない。

CRUD操作

INSERT

単数
db.users.insertOne({
  name: "John Doe",
  age: 30,
  email: "johndoe@example.com",
  address: { city: "New York", state: "NY" }
})

複数
db.users.insertMany([
  {
    name: "Alice",
    age: 25,
    email: "alice@example.com",
    address: { city: "San Francisco", state: "CA" }
  },
  {
    name: "Bob",
    age: 28,
    email: "bob@example.com",
    address: { city: "Los Angeles", state: "CA" }
  }
])

SELECT

全件取得
db.users.find()

条件付きで取得
db.users.find({ age: { $gt: 26 } })  // ageが26以上

条件付きで1件のみ取得
db.users.findOne({ email: "johndoe@example.com" })

ソート条件付きで先頭1件のみ取得

e.g. ageフィールドで昇順にソートして先頭1件を取得

db.users.find().sort({ age: 1 }).limit(1)

e.g. ageフィールドで降順にソートして先頭1件を取得

db.users.find().sort({ age: -1 }).limit(1)

UPDATE

単数
db.users.updateOne(
  { email: "johndoe@example.com" },  // 条件
  { $set: { age: 31 } }  // 更新内容
)

複数
db.users.updateMany(
  { age: { $lt: 30 } },  // 条件
  { $set: { status: "young" } }  // 更新内容
)

DELETE

単数
db.users.deleteOne({ email: "johndoe@example.com" })

複数
db.users.deleteMany({ age: { $lt: 30 } })


◆やや込み入った操作例

実際に業務で行った操作の備忘録。(フィールド名などは全て仮)

以下のような構造のドキュメントがあり、コレクション全体からelementType99に該当するpropertiesの要素を消したいという要求があった。

{
  _id: Long('123456'),
  flag: false,
  properties: [
    {
      elementType: Long('31'),
      name: 'abc',
      points: [1.11, 2.22, 3.33]
    },
    {
      elementType: Long('99'),
      name: 'def',
      memo: { contents: 'example' }
    }
  ]
}

これを下記の状態にしたい。

{
  _id: Long('123456'),
  flag: false,
  properties: [
    {
      elementType: Long('31'),
      name: 'abc',
      points: [1.11, 2.22, 3.33]
    }
  ]
}

この場合、以下のコマンドで実現できる。

db.account.updateMany(
  { },  // 条件なし(全体)
  { $pull: { properties: { elementType: 99 } } }  // $pullで配列から指定された要素を削除
)