MongoDBを操作してみる
背景
今更ながらMongoDBを再学習中です。
今回は、コマンドラインからMongoDBを操作してみます。
操作
データの追加と参照
ドキュメントusersに{username:"hashito"}を追加してみます。
test> db.users.insert({username:"hashito"})
DeprecationWarning: Collection.insert() is deprecated. Use insertOne, insertMany, or bulkWrite.
{
acknowledged: true,
insertedIds: { '0': ObjectId("63509ddb39e7cde9bce5f310") }
}
MongoDBではアクセスした瞬間にドキュメントが生成されるようです。
基本的な方法で、データを参照してみます。
また、insertは非推奨になっていることがわかります。
insertOneかinsertMany、bulkWriteの利用を推奨されています。
こちらの記載通り1件追加の場合はinsertOneを利用し、複数個の場合はinsertManyかbulkWriteを利用すれば問題ないものと思われます。
test> db.users.find()
[ { _id: ObjectId("63509ddb39e7cde9bce5f310"), username: 'hashito' } ]
.find()は引数を利用することでフィルタリングなどもあるようですが、一旦は引数無しで利用します。
ドキュメントusersの中にはデータが1つしかないことがわかります。
ドキュメントのデータ数をカウントしてみます。
db.users.count()という関数を利用します。
test> db.users.count()
DeprecationWarning: Collection.count() is deprecated. Use countDocuments or estimatedDocumentCount.
1
countという関数は非推奨であるためcountDocumentsかestimatedDocumentCountを利用するように言われます。
2つを要望していますがどちらがいいという議論はあるようです…
test> db.users.countDocuments()
1
test> db.users.estimatedDocumentCount()
1
データを追加して結果を再確認してみます。
test> db.users.insert({username:"hashito2"})
{
acknowledged: true,
insertedIds: { '0': ObjectId("6350a7a139e7cde9bce5f311") }
}
test> db.users.estimatedDocumentCount()
2
test> db.users.countDocuments()
2
test> db.users.find()
[
{ _id: ObjectId("63509ddb39e7cde9bce5f310"), username: 'hashito' },
{ _id: ObjectId("6350a7a139e7cde9bce5f311"), username: 'hashito2' }
]
データのフィルタリング
.find関数で引数を指定する事により、特定のusernameを持っているデータのみにフィルタリングする事ができます。
test> db.users.find({username:"hashito"})
[ { _id: ObjectId("63509ddb39e7cde9bce5f310"), username: 'hashito' } ]
hashito2という名前のユーザは検索されない事がわかります。
データの更新
update関数を利用することでデータを更新する事ができます。
test> db.users.update({username:"hashito"},{$set:{city:"tokyo"}})
DeprecationWarning: Collection.update() is deprecated. Use updateOne, updateMany, or bulkWrite.
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
test> db.users.find({username:"hashito"})
[
{
_id: ObjectId("63509ddb39e7cde9bce5f310"),
username: 'hashito',
city: 'tokyo'
}
]
こちらのupdate関数も同様に非推奨ですね…(私が参考にしている本が古いため申し訳ないです。)
アップデートする対象が1件の場合はupdateOneで複数個の場合は updateMany bulkWriteのいづれかを利用してください。
値の削除を行う場合もupdate系の関数を利用します。
test> db.users.updateOne({username:"hashito"},{$unset:{city:1}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
test> db.users.find({username:"hashito"})
[ { _id: ObjectId("63509ddb39e7cde9bce5f310"), username: 'hashito' } ]
少し高度な検索
少し高度な検索を行うため、要素を追加します。
f.moviesに["a","b"]または["x","b"]を追加しています。
test> db.users.update({username:"hashito"},{$set:{f:{movies:["a","b"]}}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
test> db.users.update({username:"hashito2"},{$set:{f:{movies:["x","b"]}}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
test> db.users.find()
[
{
_id: ObjectId("63509ddb39e7cde9bce5f310"),
username: 'hashito',
f: { movies: [ 'a', 'b' ] }
},
{
_id: ObjectId("6350a7a139e7cde9bce5f311"),
username: 'hashito2',
f: { movies: [ 'x', 'b' ] }
}
]
この中で、f.movies.bのみを持っているデータを抽出します。
test> db.users.find({"f.movies":"b"})
[
{
_id: ObjectId("63509ddb39e7cde9bce5f310"),
username: 'hashito',
f: { movies: [ 'a', 'b' ] }
},
{
_id: ObjectId("6350a7a139e7cde9bce5f311"),
username: 'hashito2',
f: { movies: [ 'x', 'b' ] }
}
]
この中で、f.movies.xのみを持っているデータを抽出します。
test> db.users.find({"f.movies":"x"})
[
{
_id: ObjectId("6350a7a139e7cde9bce5f311"),
username: 'hashito2',
f: { movies: [ 'x', 'b' ] }
}
]
データの削除
remove関数を利用すればデータの削除をできます。
このときにfindと同じ形式でフィルタリングする事が可能です。
test> db.users.remove({"f.movies":"x"})
DeprecationWarning: Collection.remove() is deprecated. Use deleteOne, deleteMany, findOneAndDelete, or bulkWrite.
{ acknowledged: true, deletedCount: 1 }
test> db.users.find()
[
{
_id: ObjectId("63509ddb39e7cde9bce5f310"),
username: 'hashito',
f: { movies: [ 'a', 'b' ] }
}
]
findの結果を見れば削除が成功している事がわかります。
こちらもremove関数は非推奨のようです…
アップデートする対象が1件の場合はdeleteOneまたはfindOneAndDeleteで複数個の場合は deleteMany bulkWriteのいづれかを利用してください。
また、全て削除したい場合はdrop関数を利用します。
test> db.users.drop()
true
test> db.users.find()
大量のデータ追加
MongoDBのインターフェイスはJavascriptになっています。
そのため、下記のようなコードを実行し大量のデータを追加する事ができます。
※データは挿入に数秒かかる場合があるためご注意ください。
test> for(i=0;i<20000;i++){db.numbers.insertOne({num:i})}
{
acknowledged: true,
insertedId: ObjectId("6350b49a39e7cde9bce64131")
}
test> db.numbers.countDocuments()
20000
最終的に2万個のデータが追加できたのがわかると思います。
余談
上記の様に、1個1個保存した場合に時間がかかってしまいます。
ですので、insertManyを使って一括でデータを保存したほうが高速に保存ができるものと思います。
下記のコードは2000個の{num:x}を作成しています。
test> db.numbers2.insertMany(new Array(20000).fill(0).map((v,i)=>{return {num:i}}))
実行したところ、数秒で終わりました。個別に1個ずつ追加するよりやっぱり早いですね…
test> db.numbers2.find({num:19})
[ { _id: ObjectId("6350bab139e7cde9bce64145"), num: 19 } ]
test> db.numbers2.count()
20000
Discussion