tweeeetyのぶろぐ的めも

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

mongodbでdistinctと$or、$and、$lte、$gteの使ってみるサンプル

mongoクエリーの基本ですが、
読めばわかるけど、使ってみて覚えるのが良いですよね!

かなり基本項目ですが
distinctとwhere句に使う$or、$and、$lte、$gteについての忘れないようにメモです

サンプルのながれはこんな感じ

1.サンプル入れる
2.distinct
3.$or
4.$and
5.$lte
6.$gte
7.distinctと複合条件サンプル

ってことで、サンプルデータを入れるところからやっておきます。

1.サンプル入れる

これから試すためのサンプルですが、てきとーに学校の成績データをmongoで管理してたらってゆー体でやります

サンプルデータを入れるスクリプト
/* ユーザ */
var users = [
  {id: "a0001", "name": "hoge"},
  {id: "a0002", "name": "piyo"},
  {id: "a0003", "name": "fuga"}
]

/* 学期 */
var terms = { "1": "first_term", "2": "second_term", "3": "third_term"};

/* 教科 */
var subjects = ["japanese", "math", "english"];

/* ランダムに点数を返却(1〜100) */
var markRamdom = function(){ return Math.floor(Math.random() * 100 + 1); }


/* 成績データをinsert */
for(var idx in users){

  for(var term in terms){
  
    var tmpMarks = {};
    for(var i in subjects){
      tmpMarks[subjects[i]] = markRamdom();
    }
    
    db.school_record.insert({
      "info" : {"user_id": users[idx].id, "name": users[idx].name, "term": term},
      "mark" : tmpMarks
      })
  }
}
結果
> db.school_record.find()
{ "_id" : ObjectId("532056e52ee9dde960cd50eb"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "1" }, "mark" : { "japanese" : 70, "math" : 49, "english" : 13 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ed"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "3" }, "mark" : { "japanese" : 19, "math" : 48, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ee"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "1" }, "mark" : { "japanese" : 16, "math" : 31, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ef"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "2" }, "mark" : { "japanese" : 63, "math" : 19, "english" : 32 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f0"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "3" }, "mark" : { "japanese" : 34, "math" : 4, "english" : 76 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f1"), "info" : { "user_id" : "a0003", "name" : "fuga", "term" : "1" }, "mark" : { "japanese" : 58, "math" : 51, "english" : 1 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f2"), "info" : { "user_id" : "a0003", "name" : "fuga", "term" : "2" }, "mark" : { "japanese" : 78, "math" : 94, "english" : 86 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f3"), "info" : { "user_id" : "a0003", "name" : "fuga", "term" : "3" }, "mark" : { "japanese" : 47, "math" : 61, "english" : 15 } }

構造がこうのほうがいいんじゃね?とかってのは目をつむってくださいw

2.distinct

これは(uu)ユニークユーザとか求めるときはいいですよね

使い方

db.collection.distinct("distinctするKey", {"絞りこむ条件"})

とりあえずユニークなユーザを出してみる
>db.school_record.distinct("info.user_id")
[ "a0001", "a0002", "a0003" ]

3.$or

使い方

条件1 or 条件2のパターンです

db.collection.find({$or: [{条件1}, {条件2}]})

ユーザが"hoge"または"piyo"さんを出してみる
> db.school_record.find({$or:[{"info.name": "hoge"}, {"info.name": "piyo"}]})
{ "_id" : ObjectId("532056e52ee9dde960cd50eb"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "1" }, "mark" : { "japanese" : 70, "math" : 49, "english" : 13 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ed"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "3" }, "mark" : { "japanese" : 19, "math" : 48, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ee"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "1" }, "mark" : { "japanese" : 16, "math" : 31, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ef"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "2" }, "mark" : { "japanese" : 63, "math" : 19, "english" : 32 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f0"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "3" }, "mark" : { "japanese" : 34, "math" : 4, "english" : 76 } }

慣れれば簡単ですが、最初はちょっと戸惑いましたw

直感で考えると"name"が"hoge"or"piyo"だから指定するkeyの書き出しは
find({"info.name": {$or:---省略---
みたいになるのかなって想像してましたw

4.$and

使い方

条件1 and 条件2のパターンです

db.collection.find({$and: [{条件1}, {条件2}]})

ユーザが"hoge"かつ、学期が"1"のドキュメントを出してみる
> db.school_record.find({$and:[{"info.name": "hoge"}, {"info.term": "1"}]})
{ "_id" : ObjectId("532056e52ee9dde960cd50eb"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "1" }, "mark" : { "japanese" : 70, "math" : 49, "english" : 13 } }

5.$lte

lteは記号だと「<=」です(左がkeyだとして)
eはequalなので、つけなければとうぜん「<」になります。

使い方

"あるkey"が"ある値"以下のパターンです

db.collection.find({"あるKey": {$lte: ある値}})

japaneseが20点以下の人出してみる
> db.school_record.find({"mark.japanese": {$lte: 20}})
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ed"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "3" }, "mark" : { "japanese" : 19, "math" : 48, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ee"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "1" }, "mark" : { "japanese" : 16, "math" : 31, "english" : 38 } }

6.$gte

gteは記号だと「>=」です(左がkeyだとして)
あとはlteと同じですね

使い方

"あるkey"が"ある値"以上のパターンです

db.collection.find({"あるKey": {$gte: ある値}})

englishが90点以下の人出してみる
> db.school_record.find({"mark.english": {$gte: 90}})
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }

7.distinctと複合条件サンプル

ってことであとは混ぜてみるだけです

2学期に数学が10点以下の人
> db.school_record.find({$and:[ {"info.term": "2"}, {"mark.math": {$lte: 10}} ]})
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }
全学期、全教科を通して20点以下を取ったことあるドキュメント

"ドキュメント"って言葉がポイントですね
取ったことある人、の場合はこの次にdistinctでやります

> db.school_record.find({$or:[ {"mark.japanese":  {$lte: 20}}, {"mark.math": {$lte: 20}}, {"mark.english": {$lte: 20}} ]})
{ "_id" : ObjectId("532056e52ee9dde960cd50eb"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "1" }, "mark" : { "japanese" : 70, "math" : 49, "english" : 13 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ec"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "2" }, "mark" : { "japanese" : 11, "math" : 9, "english" : 97 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ed"), "info" : { "user_id" : "a0001", "name" : "hoge", "term" : "3" }, "mark" : { "japanese" : 19, "math" : 48, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ee"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "1" }, "mark" : { "japanese" : 16, "math" : 31, "english" : 38 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50ef"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "2" }, "mark" : { "japanese" : 63, "math" : 19, "english" : 32 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f0"), "info" : { "user_id" : "a0002", "name" : "piyo", "term" : "3" }, "mark" : { "japanese" : 34, "math" : 4, "english" : 76 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f1"), "info" : { "user_id" : "a0003", "name" : "fuga", "term" : "1" }, "mark" : { "japanese" : 58, "math" : 51, "english" : 1 } }
{ "_id" : ObjectId("532056e52ee9dde960cd50f3"), "info" : { "user_id" : "a0003", "name" : "fuga", "term" : "3" }, "mark" : { "japanese" : 47, "math" : 61, "english" : 15 } }
全学期、全教科を通して20点以下を取ったことある人

人だけ欲しいのでdistinctと↑の条件を使います

> db.school_record.distinct("info.name", {$or:[ {"mark.japanese":  {$lte: 20}}, {"mark.math": {$lte: 20}}, {"mark.english": {$lte: 20}} ]})
[ "hoge", "piyo", "fuga" ]

結果全員でしたw

ってことで、基本中の基本ですが、あえて書いておいてみました(^-^v)