tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

mongodbのクエリー使ってみるテスト(insert、update($set,$setOnInsert,multi,upsert)、saveとか)

はじめに

mongodbを最近使ってるのでinsert、update系のテストです
sqlだと簡単なこともmongoクエリーになったら試してみないと結構違う感じですね

てことでさっそく

ながれ

1.INSERT
2.UPDATE
3.複数件のUPDATE(update, multi)
4.UPDATE or INSERT的な1(update, upsert)
5.UPDATE or INSERT的な2(save)
6.NOUPDATE or INSERT的な(update, $setOnInsert, upsert)

1.INSERT

基本構文

db.コレクション名.insert({ドキュメントデータ});

ためし

余計なこともしてみますがinsert。

※無いcollectionを指定 -> 特に何も表示されない
>db.testcol.find()

※findしただけではcollectionはできない
>show collections
system.indexes
system.users

※まだないcollectionを指定してinsert
>db.test.insert({"_id": "a00001", "user_info" : {"name": "hoge", "age": 10}, "user_prof" : {"work": 0, "smorker": 0 } })
>db.test.insert({"_id": "a00002", "user_info" : {"name": "fuga", "age": 21}, "user_prof" : {"work": 1, "smorker": 0 } })
>db.test.insert({"_id": "a00003", "user_info" : {"name": "piyo", "age": 33}, "user_prof" : {"work": 1, "smorker": 1 } })
>db.test.insert({"_id": "a00004", "user_info" : {"name": "waru", "age": 40}, "user_prof" : {"work": 0, "smorker": 1 } })

※collectionごと作成される
>show collections
system.indexes
system.users
test

※すでにあるkeyをinsertしてみる
>db.test.insert({"_id": "a00001", "user_info" : {"name": "hoge", "age": 10}, "user_prof" : {"work": 0, "smorker": 0 } })
E11000 duplicate key error index: testdb.test.$_id_  dup key: { : "a00001" }

insertについてはほんとにそのままですね

2.UPDATE

基本のupdateから

基本構文

db.コレクション名.update({条件}, { $set: {更新するドキュメントデータ} });

ためし
※存在しないkeyでupdateしてみる -> 特に何も怒られないがfindしてみると追加はされてない
>db.test.update({"_id": "a00005"}, {$set: {"user_info" : {"name": "waru", "age": 40}, "user_prof" : {"work": 0, "smorker": 1 }}})
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "work" : 0, "smorker" : 0 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }

※a00001のuser_infoのageをupdateしてみる
>db.test.update({"_id": "a00001"}, {$set:{"user_info.age": 18}})
>db.test.find({"_id": "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "work" : 0, "smorker" : 0 } }

※a00001のuser_profをまるっとupdateしてみる
>db.test.update({"_id": "a00001"}, {$set:{"user_prof": { "baka" : 0, "aho" : 0 }}})
>db.test.find({"_id": "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "baka" : 0, "aho" : 0 } }

※一応戻す
>db.test.update({"_id": "a00001"}, {$set:{"user_prof": { "work" : 0, "smorker" : 0 }}})

まぁこれも普通な感じですね

複数件のUPDATE(update, multi)

複数件のupdateです。
mysqlとかだとwhere句で指定したものすべてって感じですが、mongoではあえて指定しないとダメなようです

基本構文

db.コレクション名.update({条件}, { $set: {更新するドキュメントデータ} }, {multi: true});

ためし
※特に指定なしでsmorkerが0の人をsmorker=>2にしてみる
>db.test.update({"user_prof.smorker": 0}, {$set: {"user_prof.smorker" : 2}})

※全部表示してみる -> 最初にmatchした1件しか更新されない
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "work" : 0, "smorker" : 2 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }

※いったん戻してからmulti=>falseを指定してsmorker=>2にしてみる
>db.test.update({"_id": "a00001"}, {$set:{"user_prof": { "work" : 0, "smorker" : 0 }}})
>db.test.update({"user_prof.smorker": 0}, {$set: {"user_prof.smorker" : 2}}, {multi: false})

※表示 -> 1件のみupdateされてる
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "work" : 0, "smorker" : 2 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }

※再度いったん戻してからmulti=>trueを指定してsmorker=>2にしてみる
>db.test.update({"_id": "a00001"}, {$set:{"user_prof": { "work" : 0, "smorker" : 0 }}})
>db.test.update({"user_prof.smorker": 0}, {$set: {"user_prof.smorker" : 2}}, {multi: true})

※表示 -> 2件updateされてる
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "work" : 0, "smorker" : 2 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 2 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }

※いったん戻す
>db.test.update({"_id": "a00001"}, {$set:{"user_prof": { "work" : 0, "smorker" : 0 }}})
>db.test.update({"_id": "a00002"}, {$set:{"user_prof": { "work" : 1, "smorker" : 0 }}})

4.UPDATE or INSERT的な1(update, upsert)

2.UPDATEでやった存在しないkeyでのupdateをやってみます

基本構文

db.コレクション名.update({条件}, { $set: {更新するドキュメントデータ} }, {upsert: true});

ためし
※存在しないkeyでupdateしてみる
>db.test.update({"_id": "a00005"}, {$set: {"user_info" : {"name": "waru", "age": 40}, "user_prof" : {"work": 0, "smorker": 1 }}}, { upsert: true })

※表示 -> a00005が追加されてる
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 18 }, "user_prof" : { "work" : 0, "smorker" : 0 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00005", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }

5.UPDATE or INSERT的な2(save)

4.UPDATE or INSERT的な1と似てますかね。

基本構文

db.コレクション名.save({ドキュメントデータ});

ためし
※a00001のuser_profをまるっと違う値でsaveしてみる
>db.test.save({"_id": "a00001", "user_info" : {"name": "hoge", "age": 10}, "user_prof" : {"nemui": 0, "darui": 0 } })

※表示 -> まるっと更新されている
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※無いデータのa00006をsaveしてみる
>db.test.insert({"_id": "a00006", "user_info" : {"name": "dare", "age": 60}, "user_prof" : {"work": 1, "smorker": 1 } })

※表示 -> 追加されてる
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00005", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00006", "user_info" : { "name" : "dare", "age" : 60 }, "user_prof" : { "work" : 1, "smorker" : 1 } }

やってみた所感としては
行動ログなんかのデータをユーザごとに、
・無ければある固定ドキュメントでinsert
・あったらupdate&upsert
みたいな感じよりは固定のデータでsaveのほうが使いやすそう?
※速度的な感じは検証してないので今度にでもやってみます


6.NOUPDATE or INSERT的な(update, $setOnInsert, upsert)

基本構文

db.コレクション名.update({条件}, { $setOnInsert: {更新するドキュメントデータ} }, {upsert: true});

upsert(update + insert)は、
・存在すればupdate
・存在しなければinsert
ですが、$setOnInsetを指定することで存在しなければ初期値としてINSERT、UPDATEの場合は無視みたいです。

ためし
※やる前のa00001を表示
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※a00001のuser_infoをsetOnInsert&upsert=trueでupdateしてみる
>db.test.update({"_id": "a00001"}, {$setOnInsert:{"user_info": { "baka" : 0, "aho" : 0 }}}, {upsert: true})

※a00001は更新されてない
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※a00001のuser_infoをsetOnInsert&upsert=falseでupdateしてみる
>db.test.update({"_id": "a00001"}, {$setOnInsert:{"user_info": { "baka" : 0, "aho" : 0 }}}, {upsert: false})

※falseでもa00001は更新されてない
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※a00001のまだ存在しないkeyドキュメントをsetOnInsert&upsert=falseでupdateしてみる
>db.test.update({"_id": "a00001"}, {$setOnInsert:{"tekitou": { "baka" : 0, "aho" : 0 }}}, {upsert: false})

※falseでもa00001は更新されてない
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※a00001のまだ存在しないkeyドキュメントをsetOnInsert&upsert=trueでupdateしてみる
>db.test.update({"_id": "a00001"}, {$setOnInsert:{"tekitou": { "baka" : 0, "aho" : 0 }}}, {upsert: true})

※falseでもa00001は更新されてない
>db.test.find({ "_id" : "a00001"})
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }

※存在しないa00007をsetOnInsert&upsert=trueでupdateしてみる
>db.test.update({"_id": "a00007"}, {$setOnInsert:{"tekitou": { "baka" : 0, "aho" : 0 }}}, {upsert: true})

※a00007が追加されてる
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00005", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00006", "user_info" : { "name" : "dare", "age" : 60 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00007", "tekitou" : { "baka" : 0, "aho" : 0 } }

※存在しないa00008をsetOnInsert&upsert=falseでupdateしてみる
>db.test.update({"_id": "a00008"}, {$setOnInsert:{"tekitou": { "baka" : 0, "aho" : 0 }}}, {upsert: false})

※a00008は追加されない
>db.test.find()
{ "_id" : "a00001", "user_info" : { "name" : "hoge", "age" : 10 }, "user_prof" : { "nemui" : 0, "darui" : 0 } }
{ "_id" : "a00002", "user_info" : { "name" : "fuga", "age" : 21 }, "user_prof" : { "work" : 1, "smorker" : 0 } }
{ "_id" : "a00003", "user_info" : { "name" : "piyo", "age" : 33 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00004", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00005", "user_info" : { "name" : "waru", "age" : 40 }, "user_prof" : { "work" : 0, "smorker" : 1 } }
{ "_id" : "a00006", "user_info" : { "name" : "dare", "age" : 60 }, "user_prof" : { "work" : 1, "smorker" : 1 } }
{ "_id" : "a00007", "tekitou" : { "baka" : 0, "aho" : 0 } }

なるほど。
やってみた所感としては、$setOnInsertとupsert=trueを組み合わせることで
・間違って上書きとかしたくない

でも処理コケたくない
みたいな場合に使うって感じでしょうか。
※INSERTだとduplicate key error indexとか出るので。


少しだけしかやれてませんが、まだまだ覚えなきゃ使いこなせないですね(>_<)