1. 程式人生 > >MongoDB資料庫基本語法練習——查詢篇

MongoDB資料庫基本語法練習——查詢篇

MongoDB資料庫基本語法練習——查詢篇


MongoDB是一個介於關係型資料庫和菲關係型資料庫之間的產品,其最大的特點是它支援的查詢語言非常強大,且其語法有點類似面向物件的查詢語言幾乎可以實現類似關係型資料庫單表查詢的絕大部分功能。
下面是我本人練習MongoDB資料庫基本語法(查詢篇)的JavaScript程式碼(編輯環境:Robo 3T-1.2 綠色版):


/***************批量插入資料*****************/

user1 = {

    "_id":1,

    "name":"zhangsan",

    "age":1,

    "hobbies":["music", "read"],

    "addr":{

        "country":"China",

        "city":"BJ"

    }

}

user2 = {

    "_id":2,

    "name":"lisi",

    "age":2,

    "hobbies":["music", "read"],

    "addr":{

        "country":"China",

        "city":"SH"

    }

}

user3 = {

    "_id":3,

    "name":"wangwu",

    "age":3,

    "hobbies":["music", "read"],

    "addr":{

        "country":"China",

        "city":"GZ"

    }

}

user4 = {

    "_id":4,

    "name":"zhaoliu",

    "age":4,

    "hobbies":["music", "read"],

    "addr":{

        "country":"China",

        "city":"SZ"

    }

}

user5 = {

    "_id":5,

    "name":"tianqi",

    "age":5,

    "hobbies":["music", "read"],

    "addr":{

        "country":"China",

        "city":"TY"

    }

}

db.user.insertMany([user1, user2, user3, user4, user5])

/**

 *1、查詢所有

 */

db.ser.find() //等同於db.user.find({})

db.user.distinct("age")//去重

db.user.find().pretty()//格式化的方式來顯示所有文件

//select * from user where id != 3

/**

 *3、比較查詢

 * =,!= ('$ne') ,> ('$gt') ,< ('$lt') ,>= ('$gte') ,<= ('$lte')

 */

//select * from user where id = 3
db.user.find({"_id":3})

//select * from user where id != 3
db.user.find({"_id":{"$ne":3}})

//select * from user where id > 3
db.user.find({"_id":{"$gt":3}}) 

//select * from user where age < 3
db.user.find({"_id":{"$lt":3}})

//select * from user where id >= 3
db.user.find({"_id":{"$gte":3}})

//select * from user where id <= 3
db.user.find({"_id":{"$lte":3}})

/**

 *3、邏輯查詢

 * $and,$or,$not

 */

// select * from user where id >=3 and id <=4;
db.user.find({"_id":{"$gte":3,"$lte":4}})

// select * from user where id >=3 and id <=4 and age >=4;
db.user.find({

    "_id":{"$gte":3,"$lte":4},

    "age":{"$gte":4}

})

db.user.find({

    "$and": [

        {"_id": {"$gte":3, "$lte":4}},

        {"age": {"$gte":4}}

    ]

})

// select * from user where id >=0 and id <=1 or id >=4 or name = "tianqi";
db.user.find({

    $or: [

        {"_id": {$gte:0, $lte:1}},

        {"_id": {$lte:4}},

        {"name": "tianqi"}

    ]

})

// select * from user where id % 2 = 1;
db.user.find({"_id":{"$mod":[2,1]}})

//上一條取反

db.user.find({

    "_id":{"$not":{"$mod":[2,1]}}

})

/**

 *4、成員查詢

 * $in , $nin

 */

// select * from user where age in (1,2,3);
db.user.find({"age":{"$in":[1,2,3]}})

// select * from user where name not in ("zhangsan","lisi");
db.user.find({"name":{"$nin":["zhangsan","lisi"]}})

/**

 *5、$type操作符查詢

 * MongoDB可以使用的型別操作符:1-Double、2-String、3-Object、4-Array、5-Binary Data、8-Boolan、9-Date ...

 */

// 查詢name是字串型別的資料
db.user.find({name:{$type:2}})

/**

 *6、正則查詢

 * 正則定義在/ /內

 */	

// select * from user where name regexp '^z.*?(u|i)$';
// 匹配規則:z開頭、n或u結尾,不區分大小寫
db.user.find({'name':/^z.*?(n|u)$/i})

/**

 *7、投影查詢

 * 1用來顯示欄位而0是用來隱藏欄位,_id會預設顯示出來。

 */

// select name,age from user where id=3;
db.user.find({'_id':3},{'_id':0,'name':1,'age':1})

// select name,age from user where name regexp "^z.*(n|u)$";
db.user.find({

    "name":/^z.*(n|u)$/i

},

{

    "_id":0,

    "name":1,

    "age":1

}

)

/**

 *8、陣列查詢

 * 查詢陣列相關

 */

// 查hobbies中有dancing的人
db.user.find({

    "hobbies":"music"

})

// 檢視既有dancing愛好又有tea愛好的人
db.user.find({

    "hobbies":{"$all":["music","read"]}

})

// 檢視索引第2個愛好為dancing的人
db.user.find({

    "hobbies.2":"read"

})

// 檢視所有人的第1個到第3個愛好,第一個{}表示查詢條件為所有,第二個是顯示條件
db.user.find(

{},

{

    "_id":0,

    "name":0,

    "age":0,

    "addr":0,

    "hobbies":{"$slice":[0,2]},

}

)

// 檢視所有人最後兩個愛好,第一個{}表示查詢條件為所有,第二個是顯示條件
db.user.find(

{},

{

    "_id":0,

    "name":0,

    "age":0,

    "addr":0,

    "hobbies":{"$slice":-2},

}

)

// 查詢子文件有"country":"China"的人
db.user.find(

{

    "addr.country":"China"

}

)

/**

 *9、排序查詢

 * 1 為升序排列,而-1是用於降序排列

 */

// 按姓名正序
db.user.find().sort({"name":1})

// 按年齡倒序 按id正序
db.user.find().sort({"age":-1,'_id':1})

/**

 *10、分頁查詢

 * limit表示取多少個document,skip代表跳過幾個document

 * 分頁公式:db.user.find().skip((pageNum–1)*pageSize).limit(pageSize)   

 */

db.user.find().limit(2).skip(0) // 前兩個
db.user.find().limit(2).skip(2) // 第三個和第四個
db.user.find().limit(2).skip(4) // 第五個和第六個

/**

 *11、統計查詢

 */

// 查詢_id大於3的人數
// 方式一
db.user.count({'_id':{"$gt":3}}) 

// 方式二
db.user.find({_id:{"$gt":3}}).count()

/**

 *11、聚合查詢

 * 在MongoDB中聚合為aggregate,聚合函式主要用到$match  $group  $avg  $project  $concat,可以加"$match"也可以不加$match  

 */

// 練習Aggregate語法,先插入如下資料:

emp1 = {"_id":1,"name":"武大郎","sex":"male","age":18,"hire_date":"20170301","post":"燒餅檢察官","salary":7300.33}

emp2 = {"_id":2,"name":"武松","sex":"male","age":78,"hire_date":"20150302","post":"公務員","salary":71000000.31}

emp3 = {"_id":3,"name":"宋江","sex":"male","age":81,"hire_date":"20130305","post":"公務員","salary":78300}

emp4 = {"_id":4,"name":"林沖","sex":"male","age":73,"hire_date":"20140701","post":"公務員","salary":73500}

emp5 = {"_id":5,"name":"林沖","sex":"male","age":73,"hire_date":"20140701","post":"公務員","salary":73500}

emp6 = {"_id":6,"name":"柴進","sex":"male","age":28,"hire_date":"20121101","post":"公務員","salary":72100}

emp7 = {"_id":7,"name":"盧俊義","sex":"female","age":18,"hire_date":"20110211","post":"公務員","salary":79000}

emp8 = {"_id":8,"name":"高俅","sex":"male","age":18,"hire_date":"19000301","post":"公務員","salary":730000}

emp9 = {"_id":9,"name":"魯智深","sex":"male","age":48,"hire_date":"20101111","post":"公務員","salary":710000}

emp10 = {"_id":10,"name":"史進","sex":"female","age":48,"hire_date":"20150311","post":"打手","salary":73000.13}

emp11 = {"_id":11,"name":"李逵","sex":"female","age":38,"hire_date":"20101101","post":"打手","salary":72000.35}

emp12 = {"_id":12,"name":"周通","sex":"female","age":18,"hire_date":"20110312","post":"打手","salary":71000.37}

emp13 = {"_id":13,"name":"石秀","sex":"female","age":18,"hire_date":"20160513","post":"打手","salary":73000.29}

emp14 = {"_id":14,"name":"李忠","sex":"female","age":28,"hire_date":"20170127","post":"打手","salary":74000.33}

emp15 = {"_id":15,"name":"吳用","sex":"male","age":28,"hire_date":"20160311","post":"文人","salary":710000.13}

emp16 = {"_id":16,"name":"蕭讓","sex":"male","age":18,"hire_date":"19970312","post":"文人","salary":720000}

emp17 = {"_id":17,"name":"安道全","sex":"female","age":18,"hire_date":"20130311","post":"文人","salary":719000}

emp18 = {"_id":18,"name":"公孫勝","sex":"male","age":18,"hire_date":"20150411","post":"文人","salary":718000}

emp19 = {"_id":19,"name":"朱貴","sex":"female","age":18,"hire_date":"20140512","post":"文人","salary":717000}

db.emp.insertMany([emp1, emp2, emp3, emp4, emp5, emp6, emp7, emp8, emp9, emp10, emp11, emp12, emp13, emp14, emp15, emp16, emp17, emp18, emp19])

/**

 *$match和$group

 **/

// {"$match":{"欄位":"條件"}},可以使用任何常用查詢操作符$gt,$lt,$in等

// select * from db1.emp where post='公務員';
db.emp.aggregate([{"$match":{"post":"公務員"}}])

// select * from db1.emp where id > 3 group by post;  
db.emp.aggregate([

    {"$match":{"_id":{"$gt":3}}},

    {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}

])

// select * from db1.emp where id > 3 group by post having avg(salary) > 10000;  
db.emp.aggregate([

    {"$match":{"_id":{"$gt":3}}},

    {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}},

    {"$match":{"avg_salary":{"$gt":10000}}}

])

// {"$group":{"_id":分組欄位,"新的欄位名":聚合操作符}}
// 將分組欄位傳給$group函式的_id欄位即可
//{"$group":{"_id":"$sex"}} #按照性別分組
//{"$group":{"_id":"$post"}} #按照職位分組
//{"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多個欄位分組,比如按照州市分組
// 分組後聚合得結果,類似於sql中聚合函式的聚合操作符:$sum、$avg、$max、$min、$first、$last
//例1:select post,max(salary) from db1.emp group by post; 

db.emp.aggregate([{"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}}])

//例2:取每個部門最大薪資與最低薪資
db.emp.aggregate([{"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}}])

//例3:如果欄位是排序後的,那麼$first,$last會很有用,比用$max和$min效率高
db.emp.aggregate([{"$group":{"_id":"$post","first_id":{"$first":"$_id"}}}])

//4:求每個部門的總工資
db.emp.aggregate([{"$group":{"_id":"$post","count":{"$sum":"$salary"}}}, {"$sort": {"count": 1}}])

//5:求每個部門的人數
db.emp.aggregate([{"$group":{"_id":"$post","count":{"$sum":1}}}, {"$sort": {"count": 1}}])

// 陣列操作符

// {"$addToSet":expr}#不重複
// {"$push":expr}#重複
// 查詢崗位名以及各崗位內的員工姓名:select post,group_concat(name) from db1.emp group by post;
// 重複的也查詢出來
db.emp.aggregate([{"$group":{"_id":"$post","names":{"$push":"$name"}}}])
// 查詢結果

/* 1 */

{

    "_id" : "文人",

    "names" : [ 

        "吳用", 

        "蕭讓", 

        "安道全", 

        "公孫勝", 

        "朱貴"

    ]

}
/* 2 */
{

    "_id" : "打手",

    "names" : [ 

        "史進", 

        "李逵", 

        "周通", 

        "石秀", 

        "李忠"

    ]
}
/* 3 */
{

    "_id" : "公務員",

    "names" : [ 

        "武松", 

        "宋江", 

        "林沖", 

        "林沖", 

        "柴進", 

        "盧俊義", 

        "高俅", 

        "魯智深"

    ]

}
/* 4 */

{

    "_id" : "燒餅檢察官",

    "names" : [ 

        "武大郎"

    ]

}

// 查詢不重複的,如果有重複的保留一個
db.emp.aggregate([{"$group":{"_id":"$post","names":{"$addToSet":"$name"}}}])
// 查詢結果

/* 1 */

{

    "_id" : "文人",

    "names" : [ 

        "吳用", 

        "朱貴", 

        "蕭讓", 

        "安道全", 

        "公孫勝"

    ]

}

/* 2 */
{

    "_id" : "打手",

    "names" : [ 

        "李忠", 

        "史進", 

        "李逵", 

        "周通", 

        "石秀"

    ]

}
/* 3 */

{

    "_id" : "公務員",

    "names" : [ 

        "魯智深", 

        "高俅", 

        "宋江", 

        "林沖", 

        "盧俊義", 

        "武松", 

        "柴進"

    ]

}
/* 4 */

{

    "_id" : "燒餅檢察官",

    "names" : [ 

        "武大郎"

    ]

}

/**

 * $project

 **/

//{"$project":{"要保留的欄位名":1,"要去掉的欄位名":0,"新增的欄位名":"表示式"}}

// select name,post,(age+1) as new_age from db1.emp;
db.emp.aggregate([

    {

        $project:{

            "name":1,

            "post":1,

            "new_age":{"$add":["$age",1]}

        }

    }

])

/**

 * $sort和$limit和$skip

 **/

// 排序:{"$sort":{"欄位名":1,"欄位名":-1}} #1升序,-1降序
// 限制:{"$limit":n} 
// 跳過:{"$skip":n} #跳過多少個文件
  
// 取平均工資最高的前兩個部門
db.emp.aggregate([

{

    "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}

},

{

    "$sort":{"平均工資":-1}

},

{

    "$limit":2

}

])

// 取平均工資最高的第二個部門
db.emp.aggregate([

{

    "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}

},

{

    "$sort":{"平均工資":-1}

},

{

    "$limit":2

},

{

    "$skip":1

}

])

/**

 * $sample

 **/

// 隨機獲取3個文件
db.emp.aggregate([

    {$sample: {size:3}}

])

/**

 * $concat和$substr和$toLower和$toUpper

 **/
   
// 擷取字串
db.emp.aggregate([

    {

        $project:{

            "_id":0,

            "str": {$substr: ["$sex", 0, 2]}

        }

    }

])

// 拼接
db.emp.aggregate([

    {

        $project:{

            "name":1,

            "post":1,

            "name_sex": {$concat: ["$name", "測試拼接", "$sex"]}

        }

    }

])

// 將性別的英文轉為大寫
db.emp.aggregate([{"$project":{"sex":{"$toUpper":"$sex"}}}])

/**

 *12、索引

 * 索引通常能夠極大的提高查詢的效率,MongoDB使用 ensureIndex()方法來建立索引 

 */

db.COLLECTION_NAME.ensureIndex({KEY:1})

// 語法中 Key 值為你要建立的索引欄位,1為指定按升序建立索引,-1則為按降序來建立索引。
db.user.ensureIndex({"name":-1})

// 我們可以指定所建立索引的名字,如下所示:
db.user.ensureIndex({"name":1},{"name":"nameIndex"})

//查詢索引的語法格式如下所示:
db.COLLECTION_NAME.getIndexes()

db.user.getIndexes()

//刪除索引的語法格式如下所示:
db.COLLECTION_NAME.dropIndex(INDEX_NAME)
db.user.dropIndex("nameIndex")