MongoDB 語法介紹

在講語法之前,我們先介紹幾個在 MongoDB 常聽到的名詞!

Document

MongoDB 儲存資料的資料結構,以 JSON-Like 組合而成的結構。

 

  1. ex : name : “Tom”
  2. ex : height : 180
  3. ex : family : [‘father’, ‘mother’]

Collection

由多個 Document 所組成的,並且一個 Database 會有多個 Collection。

 

{ 
    "_id" : 1, 
    "name" : "Tom", 
    "class" : "A1", 
    "sid" : "A123",
    "family" : [ 
        { 
            "role" : "father", 
            "height" : 180, 
            "weight" : 60 
        }, {
            "role" : "mother", 
            "height" : 162,
            "weight" : 50 
        } 
    ] 
}
{ 
    "_id" : 2, 
    "name" : "Andy", 
    "class" : "A1", 
    "sid" : "A124", 
    "family" : [ 
        { 
            "role" : "father",
            "height" : 167, 
            "weight" : 93 
        }, { 
            "role" : "mother", 
            "height" : 170, 
            "weight" : 62 
        }, { 
            "role" : "sister",
            "height" : 121, 
            "weight" : 34
         } 
    ] 
}
{ 
    "_id" : 3, 
    "name" : "Mary", 
    "class" : "B1", 
    "sid" : "B123", 
    "family" : [ 
        { 
            "role" : "mother", 
            "height" : 181, 
            "weight" : 59 
        }, { 
            "role" : "brother",
            "height" : 161,
            "weight" : 85 
        }
     ] 
}

學生資料集

{ "_id" : 1, "name" : "math", "sid" : "A123", "score" : 100 }
{ "_id" : 2, "name" : "chinese", "sid" : "A123", "score" : 63 }
{ "_id" : 3, "name" : "english", "sid" : "A123", "score" : 77 }
{ "_id" : 4, "name" : "math", "sid" : "A124", "score" : 34 }
{ "_id" : 5, "name" : "chinese", "sid" : "A124", "score" : 98 }
{ "_id" : 6, "name" : "math", "sid" : "B123", "score" : 66 }
{ "_id" : 7, "name" : "chinese", "sid" : "B123", "score" : 45 }
{ "_id" : 8, "name" : "english", "sid" : "B123", "score" : 28 }

成績資料集

{ "_id" : ObjectId("593a7fb801d9d73d9b52b27f"), "name" : "A1", "sex" : [ "boy", "girl" ] }
{ "_id" : ObjectId("593a7fc101d9d73d9b52b280"), "name" : "B1", "sex" : [ "boy" ] }

班級性別資料集

{ "_id" : 1, "tags" : [ "dog", "cat" ] }
{ "_id" : 2, "tags" : [ "cat" ] }
{ "_id" : 3, "tags" : [ "mouse", "cat", "dog" ] }
{ "_id" : 4, "tags" : [ ] }

動物資料集

Find()

公式:db.collection.find({條件1, 條件2…},{欄位1, 欄位2 …})
Q1. 假如您想要知道所有學生的名字,則使用:
> db.students.find({}, {name: 1})

{ "_id" : 1, "name" : "Tom" }
{ "_id" : 2, "name" : "Andy" }
{ "_id" : 3, "name" : "Mary" }
如果上方語法以 MySQL 來表示:SELECT name FROM students

Find()

公式:db.collection.find({條件1, 條件2…},{欄位1, 欄位2 …})
Q2. 假如您想要知道班級是 A1 的學生有哪些,則使用:
> db.students.find({class: 'A1'}, {name: 1})

{ "_id" : 1, "name" : "Tom" }
{ "_id" : 2, "name" : "Andy" }
如果上方語法以 MySQL 來表示:SELECT name FROM students WHERE class = 'A1'

Find()

公式:db.collection.find({條件1, 條件2…},{欄位1, 欄位2 …})
Q3. 假如您想知道班級是 A1 的學生且學號是 A123 的名字與家庭成員有哪些,則使用:
> db.students.find({class: 'A1', sid: 'A123'},{name: 1, family: 1})

{ 
    "_id" : 1, 
    "name" : "Tom", 
    "family" : [ 
        { 
            "role" : "father", 
            "height" : 180, 
            "weight" : 60 
        }, {
            "role" : "mother", 
            "height" : 162, 
            "weight" : 50 
        } 
    ] 
}
如果上方語法以 MySQL 來表示:SELECT name, family FROM students WHERE class = 'A1' AND sid = 'A123'

Find()

公式:db.collection.find({條件1, 條件2…},{欄位1, 欄位2 …})
Q4. 假如您對於學生名字有些模糊,只記得名字開頭為 A ,又想知道這名學生的所有資料,則使用:
> db.students.find({name:/^A/})

{ 
    "_id" : 2, 
    "name" : "Andy", 
    "class" : "A1", 
    "sid" : "A124", 
    "family" : [ 
        { 
            "role" : "father", 
            "height" : 167, 
            "weight" : 93 
        }, { 
            "role" : "mother", 
            "height" : 170, 
            "weight" : 62 
        }, { 
            "role" : "sister", 
            "height" : 121, 
            "weight" : 34 
        } 
    ] 
}

如果上方語法以 MySQL 來表示:SELECT * FROM students WHERE name LIKE ‘A%’,但是這裡有些微不同,MongoDB 資源正規表示法讓查詢更自由

Find()

公式:db.collection.find({條件1, 條件2…},{欄位1, 欄位2 …})
Q5. 假如您想知道哪些學生家第一個成員是爸爸,則使用:
> db.students.find({'family.0.role': 'father'}, {name: 1})

{ "_id" : 1, "name" : "Tom" }
{ "_id" : 2, "name" : "Andy" }

FindOne()

公式:db.collection.findOne({條件1, 條件2…},{欄位1, 欄位2 …})
Q1. 假如你想知道第一個學生的名字,則使用:
> db.students.findOne({}, {name: 1})

{ "_id" : 1, "name" : "Tom" }

$gte、$gt、$lte、$lt、$ne

簡述:$gte(大於等於)、$gt(大於)、$lte(小於等於)、$lt(小於)、$ne(不等於)
Q1. 假如您想知道班上及格的科目與分數,則使用:
> db.scores.find({score: {$gte: 60}}, {name: 1, score: 1})

{ "_id" : 1, "name" : "math", "score" : 100 }
{ "_id" : 2, "name" : "chinese", "score" : 63 }
{ "_id" : 3, "name" : "english", "score" : 77 }
{ "_id" : 5, "name" : "chinese", "score" : 98 }
{ "_id" : 6, "name" : "math", "score" : 66 }

如果上方語法以 MySQL 來表示:SELECT name, score FROM scores WHERE score >= 60

$in、$nin

簡述:$in(包含)、$nin(不包含)
Q1. 假如您想知道哪個班級有女性,則使用:
> db.classes.find({sex: {$in: ['girl']}})

{ "_id" : ObjectId("593a7fb801d9d73d9b52b27f"), "name" : "A1", "sex" : [ "boy", "girl" ] }

$in 必須使用於陣列的狀況

$in、$nin

簡述:$in(包含)、$nin(不包含)
Q2. 假如您想知道哪個班級沒有女性,則使用:
> db.classes.find({sex: {$nin: ['girl']}})

{ "_id" : ObjectId("593a7fc101d9d73d9b52b280"), "name" : "B1", "sex" : [ "boy" ] }

$and、$or

簡述:$and(且)、$or(或)

公式:db.collection.find({$and: [{子條件1}, {子條件2}]})

Q1. 假如您想知道哪個班級兩種性別皆有,則使用:
> db.classes.find({$and: [{sex: {$in: ['boy']}}, {sex: {$in: ['girl']}}]})

{ "_id" : ObjectId("593a7fb801d9d73d9b52b27f"), "name" : "A1", "sex" : [ "boy", "girl" ] }

$and、$or

簡述:$and(且)、$or(或)

公式:db.collection.find({$and: [{子條件1}, {子條件2}]})

Q2. 假如您想知道哪個班級最少有一種性別,則使用:
> db.classes.find({$or: [{sex: {$in: ['boy']}}, {sex: {$in: ['girl']}}]})

{ "_id" : ObjectId("593a7fb801d9d73d9b52b27f"), "name" : "A1", "sex" : [ "boy", "girl" ] }
{ "_id" : ObjectId("593a7fc101d9d73d9b52b280"), "name" : "B1", "sex" : [ "boy" ] }

$elemMatch

簡述:$elemMatch(包含)
Q1. 假如您想知道哪個學生家庭成員有兄弟,則使用:
> db.students.find({family: {$elemMatch: {role: 'brother'}}}, {name: 1})

{ "_id" : 3, "name" : "Mary" }

$size

簡述:$size(數量)
Q1. 假如您想知道哪個學生家庭成員有三位,則使用:
> db.students.find({family: {$size: 3}}, {name: 1})
 
{ "_id" : 2, "name" : "Andy" }

$where

簡述:$where(方法)
公式:db.collection.find({$where: 'function'})
Q1. 假如你想知道哪些成績乘以 0.7 加權值後仍及格,則使用:
> db.scores.find({$where: 'function() {return this.score * 0.7 > 60}'})

{ "_id" : 1, "name" : "math", "sid" : "A123", "score" : 100 }
{ "_id" : 5, "name" : "chinese", "sid" : "A124", "score" : 98 }

$mod

簡述:$mod(除法)
公式:db.collection.find({key: {$mod: [除數, 餘數]}})
Q1. 假如你想知道哪些成績是十的倍數(沒有個位數),則使用:
> db.scores.find({score: {$mod: [10, 0]}})

{ "_id" : 1, "name" : "math", "sid" : "A123", "score" : 100 }

$slice

簡述:$slice:針對陣列進行取樣,如取出筆數或忽略筆數
公式:db.collection.find({key: {$slice: [忽略數(可無), 取出筆數]}})
Q1. 假如你想知道每個學生的第一個家長,則使用:
> db.students.find({}, {family: {$slice: 1}})

{ "_id" : 1, "name" : "Tom", "class" : "A1", "sid" : "A123", "family" : [ { "role" : "father", "height" : 180, "weight" : 60 } ] }
{ "_id" : 2, "name" : "Andy", "class" : "A1", "sid" : "A124", "family" : [ { "role" : "father", "height" : 167, "weight" : 93 } ] }
{ "_id" : 3, "name" : "Mary", "class" : "B1", "sid" : "B123", "family" : [ { "role" : "mother", "height" : 181, "weight" : 59 } ] }

$slice

簡述:$slice:針對陣列進行取樣,如取出筆數或忽略筆數
公式:db.collection.find({key: {$slice: [忽略數(可無), 取出筆數]}})
Q1. 假如你想知道每個學生的第二個家長,則使用:
> db.students.find({}, {family: {$slice: [1, 1]}})

{ "_id" : 1, "name" : "Tom", "class" : "A1", "sid" : "A123", "family" : [ { "role" : "mother", "height" : 162, "weight" : 50 } ] }
{ "_id" : 2, "name" : "Andy", "class" : "A1", "sid" : "A124", "family" : [ { "role" : "mother", "height" : 170, "weight" : 62 } ] }
{ "_id" : 3, "name" : "Mary", "class" : "B1", "sid" : "B123", "family" : [ { "role" : "brother", "height" : 161, "weight" : 85 } ] }

sort()、skip()

簡述:sort(排序)、skip(忽略)
公式:db.collection.find({}).sort({key: 1 | -1})
Q1. 假如你想知道成績由小到大的狀況,則使用::
> db.scores.find({}).sort({score: 1})

{ "_id" : 8, "name" : "english", "sid" : "B123", "score" : 28 }
{ "_id" : 4, "name" : "math", "sid" : "A124", "score" : 34 }
{ "_id" : 7, "name" : "chinese", "sid" : "B123", "score" : 45 }
{ "_id" : 2, "name" : "chinese", "sid" : "A123", "score" : 63 }
{ "_id" : 6, "name" : "math", "sid" : "B123", "score" : 66 }
{ "_id" : 3, "name" : "english", "sid" : "A123", "score" : 77 }
{ "_id" : 5, "name" : "chinese", "sid" : "A124", "score" : 98 }
{ "_id" : 1, "name" : "math", "sid" : "A123", "score" : 100 }

如果上方語法以 MySQL 來表示:SELECT * FROM scores ORDER BY ASC

sort()、skip()

簡述:sort(排序)、skip(忽略)
公式:db.collection.find({}).sort({key: 1 | -1})
Q2. 假如你想知道成績由小到大的狀況並且忽略前五筆,則使用:
> db.scores.find({}).sort({score: 1}).skip(5)

{ "_id" : 3, "name" : "english", "sid" : "A123", "score" : 77 }
{ "_id" : 5, "name" : "chinese", "sid" : "A124", "score" : 98 }
{ "_id" : 1, "name" : "math", "sid" : "A123", "score" : 100 }

如果上方語法以 MySQL 來表示:SELECT * FROM scores ORDER BY ASC LIMIT 5

group

簡述:group(群組)
Q1. 假如你想知道成績成績加總與平均,則使用:
> db.scores.group({
      initial:{sum: 0, count: 0}, 
      reduce: function(doc, aggregator) {
          aggregator.sum += doc.score; 
          aggregator.count +=1; 
       }, 
       finalize: function(doc) { 
          doc.arg = doc.sum / doc.count 
       }
  })
  
[ { "sum" : 511, "count" : 8, "arg" : 63.875 } ]

mapReduce

Q1. 統計所有動物數量,則使用:
> map = function(){
		this.tags.forEach(
        	function(z){
            	emit(z,{count:1})
             }
         )
    }
> reduce = function(key, values){
		var totoal=0; 
        for(var i=0;i<values.length; i++) 
        	total += values[i].count; 
        return {count : total};
    };
    

> db.animals.mapReduce(map,reduce,{out:'tmp'})
{
	"result" : "tmp",
	"timeMillis" : 291,
	"counts" : {
		"input" : 4,
		"emit" : 6,
		"reduce" : 2,
		"output" : 3
	},
	"ok" : 1
}
> db.tmp.find()
{ "_id" : "cat", "value" : { "count" : 3 } }
{ "_id" : "dog", "value" : { "count" : 2 } }
{ "_id" : "mouse", "value" : { "count" : 1 } }
Made with Slides.com