MongoDBのCRUD操作について
MongoDBのCRUD操作を、公式ドキュメント見つつ試していく
ローカルでMongoDB環境の用意する。
MongoDBのバージョンは8.0.5を使用。
dockerでMongoDBコンテナを起動
$ docker run -d \
--name mongodb \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=example \
-p 27017:27017 \
mongo:8.0.5
コンテナ起動できてるか確認
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a5122ddbe676 mongo:8.0.5 "docker-entrypoint.s…" 19 minutes ago Up 19 minutes 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongodb
mongoDBコンテナに接続する。
MongoDB shell(mongosh)を使っていく。
$ docker exec -it mongodb mongosh -u root -p example
Current Mongosh Log ID: 67c2bbc5fca64adc14584a20
Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.0
Using MongoDB: 8.0.5
Using Mongosh: 2.4.0
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
------
The server generated these startup warnings when booting
2025-03-01T07:12:50.014+00:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
2025-03-01T07:12:50.014+00:00: For customers running the current memory allocator, we suggest changing the contents of the following sysfsFile
2025-03-01T07:12:50.014+00:00: We suggest setting the contents of sysfsFile to 0.
2025-03-01T07:12:50.014+00:00: Your system has glibc support for rseq built in, which is not yet supported by tcmalloc-google and has critical performance implications. Please set the environment variable GLIBC_TUNABLES=glibc.pthread.rseq=0
2025-03-01T07:12:50.014+00:00: vm.max_map_count is too low
2025-03-01T07:12:50.014+00:00: We suggest setting swappiness to 0 or 1, as swapping can cause performance problems.
------
使用するデータベースでmyDBを選択
> use myDB
ここまでで準備OK
アップデート操作については以下とのこと
MongoDB では、挿入操作は単一のコレクションを対象とします。MongoDB のすべての書き込み (write) 操作は、単一のドキュメントのレベルでアトミックです。
まずは、ドキュメントのInsert
MongoDBでは、コレクションを明示的に作成しなくても、ドキュメントをinsertするとコレクションも作成してくれるよう。
insertには以下二つのメソッドがある。一つのドキュメント挿入か、複数のドキュメント挿入か
- db.collection.insertOne()
- db.collection.insertMany()
単一ドキュメントのインサート
ドキュメントに_idフィールドを指定せずにinsertすると、_id フィールドも追加される。
// insertOne
myDB> db.inventory.insertOne({
... item: 'canvas',
... qty: 100,
... tags: ['cotton'],
... size: { h: 28, w: 35.5, uom: 'cm' }
... });
{
acknowledged: true,
insertedId: ObjectId('67c2d32efca64adc14584a21')
}
// 確認
myDB> db.inventory.find({ item: 'canvas' });
[
{
_id: ObjectId('67c2d32efca64adc14584a21'),
item: 'canvas',
qty: 100,
tags: [ 'cotton' ],
size: { h: 28, w: 35.5, uom: 'cm' }
}
]
複数のドキュメントの挿入
// insertMany
myDB> db.inventory.insertMany([
{
item: 'journal',
qty: 25,
tags: ['blank', 'red'],
size: { h: 14, w: 21, uom: 'cm' }
},
{
item: 'mat',
qty: 85,
tags: ['gray'],
size: { h: 27.9, w: 35.5, uom: 'cm' }
},
{
item: 'mousepad',
qty: 25,
tags: ['gel', 'blue'],
size: { h: 19, w: 22.85, uom: 'cm' }
}
]);
{
acknowledged: true,
insertedIds: {
'0': ObjectId('67c2d85efca64adc14584a22'),
'1': ObjectId('67c2d85efca64adc14584a23'),
'2': ObjectId('67c2d85efca64adc14584a24')
}
}
insertedIdsがobjectで返される
次はクエリについて
// テストデータのinsert
mydb> db.inventory.insertMany([
{
item: 'journal',
qty: 25,
size: { h: 14, w: 21, uom: 'cm' },
status: 'A'
},
{
item: 'notebook',
qty: 50,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'A'
},
{
item: 'paper',
qty: 100,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'D'
},
{
item: 'planner',
qty: 75,
size: { h: 22.85, w: 30, uom: 'cm' },
status: 'D'
},
{
item: 'postcard',
qty: 45,
size: { h: 10, w: 15.25, uom: 'cm' },
status: 'A'
}
]);
コレクション内のすべてのドキュメントを選択
myDB> db.inventory.find({});
等価条件を指定
myDB> db.inventory.find({ status: 'D' });
クエリ演算子を使用して条件を指定
条件指定にクエリ演算子が使える
db.inventory.find({
status: { $in: ['A', 'D'] }
});
複数のフィールドに条件指定すると、AND条件になる
db.inventory.find({
status: 'A',
qty: { $lt: 40 }
});
[
{
_id: ObjectId('67c2e0e4fca64adc14584a26'),
item: 'notebook',
qty: 50,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'A'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a29'),
item: 'postcard',
qty: 45,
size: { h: 10, w: 15.25, uom: 'cm' },
status: 'A'
}
]
一方で、OR条件にするためには、$or演算子を使う
db.inventory.find({
$or: [{status: 'D'}, {qty: {$gt: 30}}]
});
[
{
_id: ObjectId('67c2e0e4fca64adc14584a26'),
item: 'notebook',
qty: 50,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'A'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a27'),
item: 'paper',
qty: 100,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'D'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a28'),
item: 'planner',
qty: 75,
size: { h: 22.85, w: 30, uom: 'cm' },
status: 'D'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a29'),
item: 'postcard',
qty: 45,
size: { h: 10, w: 15.25, uom: 'cm' },
status: 'A'
}
]
埋め込みドキュメントまたはネストされたドキュメントに対するクエリ
ドット表記でネストされたフィールドに対するクエリ
'size.uom'とシングルクォートで囲うことで「size.uom」という一つのフィールドとして扱われる
myDB> db.inventory.find({'size.uom': 'in'});
[
{
_id: ObjectId('67c2e0e4fca64adc14584a26'),
item: 'notebook',
qty: 50,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'A'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a27'),
item: 'paper',
qty: 100,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'D'
}
]
埋め込み / ネストされたドキュメントとの一致
等価条件をフィールドに指定する場合は、フィールドの順序も含め完全一致する必要がある。
これは要注意だ
myDB> db.inventory.find({size: {h:8.5, w:11, uom:'in'}});
[
{
_id: ObjectId('67c2e0e4fca64adc14584a26'),
item: 'notebook',
qty: 50,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'A'
},
{
_id: ObjectId('67c2e0e4fca64adc14584a27'),
item: 'paper',
qty: 100,
size: { h: 8.5, w: 11, uom: 'in' },
status: 'D'
}
]
// w:11とh:8.5の順序が逆なので、データ該当なし
myDB> db.inventory.find({size: { w:11, h:8.5, uom:'in'}});
配列のクエリ
配列に等価条件を指定する場合は、<value>は要素の順序を含め、完全一致するドキュメントを返す
myDB> db.inventory.find({tags: ['blank', 'red']})
[
{
_id: ObjectId('67c2f187fca64adc14584a2a'),
item: 'journal',
qty: 25,
tags: [ 'blank', 'red' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2d'),
item: 'planner',
qty: 75,
tags: [ 'blank', 'red' ],
dim_cm: [ 22.85, 30 ]
}
]
myDB> db.inventory.find({tags: ['red', 'blank']})
[
{
_id: ObjectId('67c2f187fca64adc14584a2b'),
item: 'notebook',
qty: 50,
tags: [ 'red', 'blank' ],
dim_cm: [ 14, 21 ]
}
]
配列内の順序や他の要素に関係なく"red" 要素と "blank" 要素の両方を含む配列を検索する場合は、$all 演算子を使う
myDB> db.inventory.find({tags: {$all: ['red', 'blank']}});
[
{
_id: ObjectId('67c2f187fca64adc14584a2a'),
item: 'journal',
qty: 25,
tags: [ 'blank', 'red' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2b'),
item: 'notebook',
qty: 50,
tags: [ 'red', 'blank' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2c'),
item: 'paper',
qty: 100,
tags: [ 'red', 'blank', 'plain' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2d'),
item: 'planner',
qty: 75,
tags: [ 'blank', 'red' ],
dim_cm: [ 22.85, 30 ]
}
]
tags が要素の 1 つとして文字列 "red" を含む配列があるドキュメントのクエリ
myDB> db.inventory.find({tags: 'red'});
[
{
_id: ObjectId('67c2f187fca64adc14584a2a'),
item: 'journal',
qty: 25,
tags: [ 'blank', 'red' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2b'),
item: 'notebook',
qty: 50,
tags: [ 'red', 'blank' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2c'),
item: 'paper',
qty: 100,
tags: [ 'red', 'blank', 'plain' ],
dim_cm: [ 14, 21 ]
},
{
_id: ObjectId('67c2f187fca64adc14584a2d'),
item: 'planner',
qty: 75,
tags: [ 'blank', 'red' ],
dim_cm: [ 22.85, 30 ]
}
]