MongoDB 學習筆記


MongoDB 是一種NOSQL數據庫,Node.js將其作爲主DB
MongoDB 包括:數據庫(類似於)--數據庫,集合--表,文檔--行,成員--列,ObjectID自動維護--主鍵
所有數據都是文檔形式保存的,標準json保存的
Node.js開發必需使用MongoDB
www.mongodb
安裝後在安裝目錄下新建目錄 db、log
mongod --dbpath E:/MongoDB/db //數據文件放在db目錄下
mongod --dbpath E:/MongoDB/db --port=27000  //設置端口號
mongo //連接mongo 數據庫
show database //查詢所有數據庫,會顯示一個local數據庫,這個數據庫不使用
show dbs
新建一個mongodb.conf文件裏面如下內容:
  dbpath = E:\MongoDB\db   //設置數據目錄的路徑
  logpath = E:\MongoDB\logmongodb.log  //設置日誌信息的文件路徑
  logappend = true   //打開日誌輸出操作
#  noauth = true  //不以授權的方式打開DB, 不需要登錄密碼
  auth = true//以驗證的方式打開DB,需要登錄密碼
  port = 27001   //端口號
use admin  //切換到admin用戶
db.shutdownServer()   //關閉數據庫
mongod -f E:\MongoDB\mongodb.conf  //重啓mongo服務
mongo --port=27001  //連接數據庫 帶端口號


use mldnDB //創建了數據庫,只有在數據庫裏面保存集合數據之後才能夠真正創建數據庫
db.createCollection("emp") //創建一個集合
db.dept.insert({"deptno":10, "dname":"財務部","loc":"北京"});
show collections   //查看所有集合
db.dept.find();  //db.集合名稱.find({若干條件})
   可以增加不規則的數據,內容隨便定義,db不能查看集合結構
var deptData={"deptno":20, "dname":"研發部"};
db.dept.insert(deptData);
集合中每一行記錄都會自動生成一個_id  時間戳+機器碼+ PID + 計數器
db.dept.findOne();
db.dept.remove({"_id":ObjectId("123jklj23123jkj233j2jc")});


var deptData={"deptno":50, "dname":"乞討部"};
db.dept.update({"_id":ObjectId("123jklj23123jkj233j2jc")},deptData);


db.dept.drop(); //刪除集合
db.dropDatabase(); //刪除當前所在的數據庫
db.集合.insert({json表達式}); //增加操作,‘集合’相當於表名,‘json’就是數據
db.集合.insert([{json表達式},{json表達式}]); //保存多個數據用數組,保存了2個數


db.集合名稱.find({查詢條件}[{設置顯示的字段}])
db.info.find({"url":"www.dml.com"},{"_id":0,"url":1}).pretty(); //查詢url="www.dml.com",不顯示‘_id’字段,顯示url 字段。pretty漂亮的顯示


關係查詢:等於(key:value、$eq),大於($gt),小於($lt),大於等於($gte),小於等於($lte),不等於($ne)
db.student.find({"name":"張三"});
db.student.find({"age":{"$gt":19}}); //查詢age 大於19的學生


邏輯運算:與($and)、或($or),非($not、$nor--對or求反)
db.students.find({"age":{"$gte":19, "$lte":20}});查詢年齡在19到20歲的學生
db.students.find({"age":{"$ne":{"$gte":19, "$lte":20}}}); 查詢age不是19到20歲的學生
db.students.find({"$or":[{"age":{"$gt":19}}, 
{"score":{"$gt":90}}]});查詢年齡大於等於19 或者 分數大於90的學生


求模--$mod
{"$mod":[數字,小數位]}
db.students.find({"age":{"$mod":[20,0]}}); 對年齡求模,age對20求模 於1 的數


查詢範圍:"$in"(在範圍中)、"$nin"(不在範圍中)
db.students.find({"name":{"$in":["張三","李四"]}}); name in 張三、李四的數


數組查詢:運算符:$all、$size、$slice、$elemMatch
{"$all":[內容1,內容2,..]}
student中course是一個數組列
db.students.find({"course":{"$all":["語文","數學"]}}).pretty(); //包含有"語文","數學" 的數據
db.students.find({"course.1":"數學"}).pretty(); //查詢數組中第二個內容(index=1,索引下表從0開始)爲數學的信息
db.students.find({"course":{"$size":2}}).pretty();//查詢出只參加兩門課的信息
控制數組返回的數量
db.students.find({"age":19}, {"course":{"$slice":2}}).pretty();返回年齡爲19,但是隻顯示前兩門課程(只顯示數組中 第0和1兩個數)
db.students.find({"age":19}, {"course":{"$slice":[1,2]}}).pretty();但是隻顯示中間兩門課程(只顯示數組中第1和第2兩個數)  [1,2]‘1’爲跳過量,‘2’爲返回2個數


嵌套集合運算 "$elemMatch"
db.students.find({"age":{"$gte":19, "parents":{"$elemMatch":{"job":"局長"}}}})
db.students.find({"$and":[
{"age":{"$gte":19}},
{"parents":{"$elemMatch":{"job":"局長"}}}]})


判斷某個字段是否存在,$exists true表示存在
db.students.find({"parents":{"$exists":true}}).pretty(); //顯示有parents列的數據


條件過濾 "$where", 使用where時 索引是不起作用的,屬於全表掃描
db.students.find({"$where": "this.age>20"});
db.students.find("this.age>20");
db.students.find(function(){ return this.age>20;});//屬於編寫一個操作函數
db.students.find({"$where": "function(){ return this.age>20;}"});//加$where就要加 {}
db.students.find({"$and": [ {"$where":"this.age>19"},
{"$where":"this.age<21"}]});


正則運算:模糊查詢必需使用正則表達式,使用的是Perl語言兼容的正則表達式形式
基礎語法:{key: 正則標記}
完整語法:{key: {"$regex": 正則標記,"$options": 選項}}
    對於options主要是設置正則的信息查詢標記
        "i": 忽略大小寫
        "m": 多行查詢
        "x": 空白字符串除了被轉義的或在字符類中意外的 完全被忽略
        "s": 匹配所有字符(圓點、"."),包括換行內容
    如果是直接使用(javascript), i和m 可以直接使用,而“x”和“s”必需使用"$regex"
db.students.find({"name": /谷/}) ; 查詢姓名帶"谷"的姓名,谷 沒有雙引號"
db.students.find({"name": /a/i}) ;查詢name中存在a的名稱,不區分大小寫
db.students.find({"name": {"$regex": /a/i}}).pretty() ;//完整的格式
db.students.find({"name": /語?/}).pretty() ; //之查詢出帶"語文"的數據,儘量少用?


排序操作,"sort()" 升序(1),降序(-1)
db.students.find().sort({"score": -1}).pretty(); //按照成績降序排序
自然排序:數據保存的先後順序


數據分頁顯示:skip() 表示跨過多少數據行
limit(n) 取出的數據行的個數限制
db.students.find().skip(0).limit(5).sort({"age": -1}).pretty();  顯示第一頁,0-5條
db.students.find().skip(5).limit(5).sort({"age": -1}).pretty();  顯示第二頁,5-10條,跨過5條 顯示5條


數據更新操作
mongodb修改函數很麻煩,如果關係型數據變更了,mongodb數據刪掉從新插
語法:db.集合.update(更新條件, 新的對象數據(更新操作符) , upsert,multi);
    upsert:如果要更新的數據不存在,則增加一條新的內容(true爲增加,false爲不增加)
multi:表示是否只更新滿足條件的第一行記錄,如果設置成false只更新第一條,true爲全更新。
db.students.update({"age": 19}, {"$set":{"score":100}},false,false);  將年齡是19歲的成績都更新爲100分,false爲只更新一條
db.students.update({"age": 19}, {"$set":{"score":100}},false,true);  將年齡是19歲的成績都更新爲100分,true爲都更新
db.students.update({"age": 30},{"$set":{"name":"不存在"}},true,false); 由於沒有年齡是30的數據,所以此時相當於數據創建,true爲沒有則創建
使用save()操作,找到爲更新,找不到則插入一條(用_id不會插入)
db.students.save({"_id":ObjectId("1232kj23lkjlk43"), "age":50}) //按照_id更新,將age更新爲50


修改器
$inc :將主要針對於一個數字字段,增加某個數字字段的數據內容
語法: {"$inc":{"成員":內容}}
db.students.update({"age":19, {"$inc": {"score":-30, "age":1}}}) 將所有年齡爲19歲的學生,成績減少30分,年齡加1歲  (默認只改一條,加 ,false,true 改所有)
$set :進行內容的重新設置
語法:{"$set":{"成員":""}}
db.students.update({"age":20}, {"$set":{"score":89}})  將年齡爲20歲的學生,成績設置成89分
$unset: 刪除某個成員的內容
db.students.update({"name":"張三"},{"$unset": {"age":1, "score":1}}) //將name爲張三的學生,age和score兩個成員刪掉(不是隻是刪掉內容)
$push: 相當於將內容追加到指定的成員之中(基本上是數組)
語法:${"$push": {成員 : value}}  ,增加的是數組,一次追加一個value
db.students.update({"name":"張三"},{$push :{"course": "語文"}})  //向張三添加課程信息,course字段是個數組
$pushAll  與$push類似,一次可增加多個value
db.students.update({"name":"張三"},{$pushAll :{"course": ["語文","美術"]}}) ;
$addToSet :向數組裏面增加一個新的內容,只有這個內容不存在的時候纔會增加
語法:{"$addToSet": {成員:內容}}
db.students.update({"name":"張三"},{$addToSet :{"course": "跳舞"}}) ; //會判斷要增加的內容在數組中是否已經存在了,如果不存在則增加,存在則不增加。
$pop 刪除數組內的數據
語法:{"$pop":{成員: 內容}}  ‘內容’設置成-1表示刪除數組中第一個,‘內容’ 爲1則刪除數組中最後一個
db.students.update({"name":"王五"},{"$pop":{"course":-1}}) // 刪除王五課程中第一門課
$pull 衝數組中刪除只能內容的數據
語法:{"$pull":{成員:數據}}
db.students.update({"name":"王五"},{"$pull":{"course":"音樂"}}) // 刪除王五課程中 音樂這門課
$pullAll :一次刪除多個內容
語法: {"$pullAll":{成員:[數據,數據,..]}}
db.students.update({"name":"王五"},{"$pullAll":{"course":["音樂","數學"]}}) // 刪除王五課程中 音樂、數學 這門課
$rename :爲成員名稱 重命名
語法:{"$rename":{舊成員名稱: 新成員名稱}}
db.students.update({"name":"張三"},{"$rename":{"name":"姓名"}})  //將張三的字段名‘name’ 改成 ‘姓名’,其他人不變


刪除數據
remove()
db.infos.remove({});清空infos內的數據
db.students.remove({"name": /谷/})  //刪除name中帶有 谷的數據
db.students.remove({"name": /谷/},true)  //刪除name中帶有 谷的數據,只刪除一個


遊標(重點)
數據可以一行一行操作,非常類似於resultSet數據處理
hasNext() 判斷是否有下一條數據
var curser = db.students.find();
curser.hasNext(); //返回true
curser.next(); //返回內容
while(curser.hasNext()){
var doc = curser.next();
print(doc.name);
printjson(doc); //打印所有數據
}


索引(重點)
自動創建的,手動創建
db.students.getIndexes(); 查詢所有存在的索引
顯示:{
"v" : 1,  
"key" : {"_id" : 1}, //1表示升序排序
"name" : "_id_",
"ns" : "mldn.students"
}
索引創建: db.集合名稱.ensureIndex({列 : 1})
   1表示索引按照升序的方式進行排序,如果使用降序設置‘-1’。
db.students.ensureIndex({"age" : -1}) ; 在age上設置一個降序索引
   自動設置索引名稱 “字段名稱 + 排序類型 = age_-1”
db.students.find({"age" : 19}).explain(); //返回索引的操作分析
"stage" : "COLLSCAN"  //COLLSCAN集合掃描,相當於全表掃描
"stage" : "IXSCAN" //索引掃描
db.students.ensureIndex({"age" : -1, "score":-1},{name:"age-1_score-1_ind"}) ;
db.students.find({"age":19 , "score":89}).explain();
"stage" : "KEEP_MUTATIONS"
"stage" : "IXSCAN"
db.students.find({"$or": [{"age": {$gt:19}} ,{"score": {$gt:60}}]}).hint({"age":-1 , "score":-1})  //hint強制使用索引,一般$or不會使用索引,需要hint
刪除索引:dropIndex()
db.students.dropIndex({"age":-1 , "score":-1});
刪除全部索引:指的是非"_id"的索引,所有自定義的索引
dropIndexs()
db.students.dropIndexs();


唯一索引:使該字段的內容不重複。
db.students.ensureIndex({"name":1}, {"unique":true});


過期索引 :如手機驗證碼,這個時間往往不怎麼準確
db.phones.insert({"tel":"110", "code":"111", "time": new Date()});
db.students.ensureIndex({"time":1}, {expireAfterSeconds:10}) //過期索引,在10秒後過期,10秒後(時間不準)所保存的數據就會消失


全文索引:
db.news.ensureIndex({"title":"text", "content":"text"}); //設置全文索引,字段title、content 爲全文索引
db.news.ensureIndex({"$**":"text"}); //爲所有字段設置全文檢索,儘可能別用 因爲慢。
    如果要想表示出全文索引,則使用 "$text"判斷符,
    而想要進行數據查詢,則使用  "$search"
查詢指定關鍵字:{"$search":"查詢關鍵字"}
查詢多個關鍵字(或關係):{"$search":"查詢關鍵字 查詢關鍵字  查詢關鍵字 .."}
查詢多個關鍵字(與關係):{"$search":"\"查詢關鍵字\" \"查詢關鍵字\" ..."};  //  ‘\’是轉義符  先"" 再"\"\""   再"\"查詢關鍵字\" "
查詢多個關鍵字(排除某一個):{"$search":"查詢關鍵字 查詢關鍵字 ...-"}  //最後有一個‘-’號
db.news.find({"$text":{"$search":"ggg"}}); //查詢包含‘ggg’的數據,只對設置了全文檢索的字段查找。
db.news.find({"$text":{"$search":"ggg aaa"}});//包含‘ggg’或‘aaa’的數據
db.news.find({"$text":{"$search":"\"mldn\" \"ggg\""}});  //包含有‘mldn’和‘ggg’ 的數據
db.news.find({"$text":{"$search":"\"mldn\" \"ggg\" -aaa"}});//包含‘mldn’和‘ggg’ 但是不包含‘aaa’的數據
db.news.find({"$text":{"$search":"ggg"}}, {"score":{"$meta":"testScore"}}); //$meta 查詢的準確度 值越大越準確
db.news.find({"$text":{"$search":"ggg"}}, {"score":{"$meta":"testScore"}}).sort({"score":{"$meta":"testScore"}}); //按準確率排序,降序


地理信息索引
地理信息索引分爲2類:2D平面索引、2DSphere球面索引
2D保存的都是經緯度座標
db.shop.ensureIndex({"loc":"2d"}); //給loc字段建立2d索引,
對loc進行座標位置查詢:
"$near" 查詢,查詢距離某點最近的座標點。
"$geoWithin"查詢,查詢某個形狀的點。
db.shop.find({loc:{"$near":[11,11]}}) //查找裏11,11近的座標,距離100個點內的數據返回回來。
db.shop.find({loc:{"$near":[11,11], "$maxDistance":5}}) ;設置查詢範圍,距離5個點內的數據返回回來。
在2D索引裏面支持最大距離,但是不支持最小距離。
但是可以設置一個查詢範圍,使用"$geoWithin"查詢,可以設置的範圍包括:
   矩形範圍($box):{"$box":[[x1,y1],[x2,y2]]};
   圓形範圍($center):{"$center":[[x1,y1],r]};
   多邊形($polygon):{"$polygon":[[x1,y1],[x2,y2][x3,y3],...]}
db.shop.find({loc:{"$geoWithin":{"$box":[[9,9],[11,11]]}}}) ;//查詢矩形
db.shop.find({loc:{"$geoWithin":{"$center":[[10,10],2]}}}) ;//查詢圓形


runCommand() :可以執行所有的特定的MongonDB命令
db.runCommand({"geoNear":"shop",near:[10,10],maxDistance:5,num:2}); //針對shop集合 操作,10,10附近的,maxDistance:5:表示距離5個點內的數據,  num:2:表示返回的信息量2條
    "nscanned" : 17  //掃描了17條數據
"avgDistance" : 0.5 //平均距離是0.5
"maxDistance" : 1  //最大距離是1
"time" : 5  //花費時間5號秒


聚合(重點)
MongoDB產生背景是打數據背景下,統計操作就稱爲聚合。
db.students.count(); //統計行數
db.students.count({"name":/張/i}); 查詢姓張的人 個數,不設置條件快很多


消除重複數據 distinct
操作沒有直接的函數支持,只能利用runCommand進行。
db.runCommand({"distinct":"students", "key":"name"}); //只顯示了name字段,對students表做distinct操作,查詢name字段
顯示"n":9  //去重複前的記錄數
    "nscanned":0 ,
    "nscannedObjects":9 ,//掃描對象數,越少越好
    "timems":0 ,
    "planSummary":"COLLSCAN"


group操作
db.runCommand({"group": {"ns":"students", //集合名稱students
"ksy":{"age":true},//按age分組
"initial":{"count":0}, //count初始化爲0
"condition":{"age":{"$gte":19}},//篩選條件,age大於19
"$reduce":function(doc,prev){ print("doc="+ doc +"prev="+prev)} //
}});
map是處理操作,篩選
reduce是真正統計操作


MapReduce,就是分爲兩步去做
  Map:將數據區別取出
  Reduce:負責數據的最後處理
要在MongoDB裏實現MapReduce處理,複雜度相當高
db.emps.insert({"name":"張三", "age":30, "sex":"男", "job":"clerk", "salary":8000}); 
var jobMapFun = function(){
emit(this.job,this.name); //按照job分組,取出name
}
var jobReduceFun = function(key,values){
return {"job":key, "names":values}; //key、values是個變量
}
var jobFinalizeFun(key,values){
if(key == "PRESIDENT"){
return {"job":key, "names":values, "info":"公司老大"}
}
retrun {"job":key, "name":values};
}
db.runCommand({
"mapreduce":"emps", //指定處理的表emps
"map":jobMapFun, //指定map方法jobMapFun
"reduce":jobReduceFun,
"out","t_job_emp" , //指定輸出表名 t_job_emp
"finalize":jobFinalizeFun
})
db.t_job_emp.find();


統計出各性別的人數、平均工資、最低工資、僱員數:
var sexMapFun = function(){
emit(this.sex,{"ccount":1, "csal":this.salary, "cmax":this.salary, "cmin":this.salary}); //定義好分組的條件this.sex, 定義每個集合需要取出的內容
};
var sexReduceFun = function(key,values){
var total = 0; //統計
var sum = 0; //計算工資
var max = values[0].cmax; //假設第一個數據是最高工資
var min = values[0].cmin; //假設第一個數據是最低工資
var names = new Array(); //定義數組內容
for(var x in values){ //表示循環取出裏面的數據
total += values[x].ccount; //人數增加
sum += values[x].csal; //可以循環取出所有的工資,並累加
if(max < valuesp[x].cmax){ //不是最高工資
max = values[x].cmax;
}
if(min > values[x].cmin){ //不是最低工資
min = values[x].cmin;
}
}
var avg = (sum/total).toFixed(2);
//返回處理結果
return {"count":total, "avg":avg, "sum":sum, "sin":sin};
}
db.runCommand({
"mapreduce":"emps" //指定集合名稱emps
"map":sexMapfun,
"reduce":sexReduceFun,
"out":"t_sex_emp"
});
db.t_sex_emp.find();  //大數據時代提供MapReduct支持,但是現實中不可能使用。MapReduct超級費時


聚合框架(核心)
MapReduct功能強大,但是複雜度和功能一樣強大,那麼很多時候我們需要MapReduct的功能,可以是又不想把代碼寫的太複雜,
所以從Mongo2.x版本之後開始引入了聚合框架,並且提供了聚合函數:aggregate()


group  分組操作
取出每個職位的員工數:
db.emps.aggregate([{"$group":{"_id":"$job", job_count:{"$sum":1}}}]) //使用job列作爲id列(用job分組) , job_count員工數
求出每個職位的總工資:
db.emps.aggregate([{"$group":{"_id":"$job", job_sal:{"$sum":"$salary"}}}]) //對salary列作sum計算
計算出每個職位的平均工資:
db.emps.aggregate([{"$group":{
"_id":"$job", //用job分組
"job_sal":{"$sum":"$salary"}, //對salary列作sum計算
"job_avg":{"$avg":"$salary"},// 對salary列作avg計算
"job_max":{"$max":"$salary"},
"job_min":{"$min":"$salary"} }}]); 


db.emps.aggregate([{"$group":{
"_id":"$job", //job分組
"sal_data":{"$push": "$name"} }}]); // 把每個職位的name放到數組裏顯示(沒有去重複)
取消重複數據"$addToSet"
db.emps.aggregate([{"$group":{
"_id":"$job", //job分組
"sal_data":{"$addToSet": "$name"} }}]);// 把每個職位的name放到數組裏顯示(去重複)
保留第一個數據
db.emps.aggregate([{"$group":{
"_id":"$job", //job分組
"sal_data":{"$first": "$name"} }}]);// 分組後只保留第一個name
保存最後一個數據
db.emps.aggregate([{"$group":{
"_id":"$job", //job分組
"sal_data":{"$last": "$name"} }}]);// 分組後只保留最後一個name


所有數據都是無序的,都是在內存中完成的,所以不能支持大數據量。


$project
可以利用"$project"來控制數據列的顯示規則,那麼可以執行的規則如下:
    普通列({成員 : 1|true})  表示要顯示的內容
    "_id"列({"_id":0|false})  表示"_id"列是否顯示
    條件過濾列({成員 : 表達式})  滿足表示之後的數據可以進行顯示
只顯示name、job列,不顯示"_id"
db.emps.aggregate([{"$project":{"_id":0, "name":1}}]); //_id不顯示,name顯示, 屬於數據庫的投影機制
加法("$add")減法("$subtract"),乘法("$multiply"),除法("$divide")求模("$mod")
四則運算
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"職位":"$job", //顯示job列,取別名"職位"
"salary":1 }}])

db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"job":1,
"salary":{"年薪":{"$multiply":["$salary",12]}} }}]); //計算年薪 = salary * 12
關係運算:大小比較("$cmp")、等於("$eq")、大於("$gt")、大於等於("$gte")、小於等於("$lte")、不等於("$ne")、判斷null("$ifNull"),返回邏輯型數據
邏輯運算:與("$and")、或("$or")、非("$nor")
字符串操作:連接("$concat")、截取("$substr")、轉小寫("$toLower")、轉大寫("$toUpper")、大小寫比較("$strcasecmp")
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"job":1,
"工資":"$salary", //要想顯示工資列,需要使用別名
"salary":{"$gte":["$salary",2000]} }}]); //salary顯示的是是否符合查詢  true|false如下
顯示:
{"name":"張三", "job":"CLERK", "salary":false, "工資":1000}  
{"name":"李四", "job":"CLERK", "salary":true, "工資":5000}  
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"職位":"$job", 
"job":{"$eq":["$job",{"$toUpper":"manager"}]} }}]); //將job轉換成大寫
顯示:
{"name":"張三", "job":false, "職位":"CLERK" }  
{"name":"李四", "job":true, "職位":"MANAGER"  }  
MongoDB中的數據是區分大小寫的。
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"職位":"$job", 
"job":{"$strcasecmp":["$job","manager"]} }}]);
顯示:
{"name":"張三", "job":-1, "職位":"CLERK" }  //小於爲-1 等於爲0 大於爲1
{"name":"李四", "job":0, "職位":"MANAGER"  }  


聚合框架($sort)
1表示升序,-1表示降序
db.emps.aggregate([{"$sort: {"age":-1, "salary":1}"}])
db.emps.aggregate([
{"$match":{"salary":{"$gte":1000,"$lte":10000}}}, //做match計算
{"$project":{"$_id":0, "name":1, "salary":1, "job":1}},  //控制顯示規則 0爲不顯示 1爲顯示
{"$group":{"_id":"$job", "count":{"$sum":1}, "avg":{"$avg":"$salary"}}}, //用job分組
{"$sort":{"count":-1}} //做排序,用上一行的“count”別名
]);


分頁處理 $limit、$skip
$limit:負責數據的取出個數
$skip:數據的跨過個數
db.emps.aggregate([
{"$project":{"_id":0, "name":1, "salary":1, "job":1}}, //第一行
{"$skip":3}, //先跨過3行數據 //第二行
{"$limit": 2}//取2行數據 //第三行
]);  //執行順序是:先第一行,再執行第二行,再執行第三行,所以第二行和第三行不能寫反了。


"$unwind"
查詢數據段 時候返回數組信息,但是數組不方便信息的瀏覽,所以提供有$unwind,可以將數組信息變爲獨立的字符串內容。
db.depts.aggregate([
{"$project":{"_id":0, "title":1, "bus":1}},
{"$unwind":"$bus"}]);  //相當於把數組中的數據變爲但行的數據


$geoNear
使用$geoNear可以得到附近的座標點,必須有2d索引的支持
db.shop.insert({loc:[10,10]});
db.shop.insert({loc:[12,13]});
db.shop.insert({loc:[30,50]});
db.shop.ensureIndex({"loc":"2d"}); //2d索引
db.depts.aggregate([
{"$geoNear":{"near":[11,12],   //在什麼附近
"distanceField":"loc",  //設置座標點字段
"maxDistance":1, //最遠的距離
"num":2, //返回2條記錄
"spherical":true}} //設置球面的方式
])


$out
利用此操作可以將查詢結果輸出到指定的結合裏面
將投影的結果輸出到集合裏,會新建一個新表emp_infos ,實現了表的複製操作:
db.emps.aggregate([
{"$project":{"_id":0, "name":1, "salary":1, "job":1}},
{"$out":"emp_infos"}
])


固定集合
規定集合大小,如果要保存的內容已經超過了集合的長度,那麼會採用lru的算法(最近最少使用原則)將最早的數據移出,從而保存新的數據
默認使用createCollection()函數創建,或者使用增加數據後自動創建,要使用固定集合,必須明確創建一個空集合。
創建空結合(固定集合):
db.createCollection("depts",{"capped":true, //表示有容量限制的
"size":1024,   //集合的容量,最多1024字節
"max":5});     //最多有5行記錄
元外之元--阿拉伯數字


GridFS
MongoDB裏面處置大數據的存儲 如:圖片,音樂,各種二進制
使用mongFiles命令完成
1.利用命令行進入文件所在目錄
2.將文件保存到文件庫中:
d:> mongfiles --port=27001 put photo.tif
3.查看保存的文件
d:> mongfiles --port=27001 list
4.在MongoDB裏面有一個fs系統集合,這個集合默認保存在了test集合下
show dbs;//顯示了每個db的大小
use tset;
show collections; //顯示所有的集合
db.fs.files.find();//fs是系統集合,顯示剛纔保存進來的photo.tif文件
5.刪除文件
d:>mongofiles --port=27001 delete photo.tif


用戶管理
在mongoDD裏面默認情況下只要是進行連接都可以不使用用戶名和密碼,必須符合以下幾個條件
 條件1.服務器啓動的時候打開授權認證
 條件2.需要配置用戶名和密碼
 想要配置用戶名和密碼一定是針對於一個數據庫的,
   必須先切換到mldn數據庫上:use mldn
   任何用戶都具備一個自己的操作角色,對於角色最近處的角色:read、readWrited、
db.createUser({
  "user":"hello",  //創建用戶hello
  "pwd":"java",
  "roles":[{"role":"readWrite", "db":"mldn"}]
  })
以授權的方式打開MongoDB
mongodb.conf配置文件增加如下配置
auth = true    //驗證的啓動模式
此時增加了一個驗證的啓動模式,發現依然可以不輸入用戶和密碼進行登錄,並且也可以直接進行數據庫的切換操作。
但是在使用數據庫集合的時候出現了錯誤的提示。
登錄數據庫使用 用戶名和密碼:
mongo localhost:27001/mldn -u hello -p java  //登錄數據庫mldn
如果要改密碼,那麼就請關閉授權登錄,需要noauth=true
db.changeUserPassword("hello","happy"); //修改密碼


java 連接MongoBD操作 (基於2.x驅動),MongoDB只做這些操作如下1,2,3,4,5
MongoDB實際上是作爲一個附屬數據庫存在,只有Node.js把他作爲正室,除了Node.js之外,是個不能夠單獨使用的數據庫,都需要與傳統關係型數據庫匹配使用。
public class MongoDemoA{
public static void main(){ //1111
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");//連接數據庫
if(db.authenticate("hello","happy".toCharArry())){ //進行數據庫的用戶名密碼驗證
DBCollection col = db.getCollection("deptcol");//要操作的集合名字,表名
for(int x=0;x<100 ;x++){
BasicDBObject obj = new BasicDBObject();
obj.append("deptno",1000+x);
obj.append("dname","技術部-"+x);
obj.append("loc","北京-"+x);
col.insert(obj); //保存數據
}
}
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");
DBCursor cursor= col.find().skip(0).limit(10); //得到分頁信息
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部門編號:"+ obj.get("deptno")+ "名稱"+obj.get("dname"));
}
}
client.close();
///////////
}
}
public static void main(){//2222222  大於、小於、in 查詢
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");//連接數據庫
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//設置表名
//BasicDBObject存放where條件,或者存放查詢後的數據
DBObject cond = new BasicDBObject();//準備設置查詢過濾
//只要有json格式都是用new BasicDBObject,如下
cond.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));//設置deptno的數據範圍在1000 --1020之間
//cond.put("deptno",new BasicDBObject("$in",new int[]{1001,1003,1005}));//in操作
//設置查詢條件 如下
DBCursor cursor = col.find(cond).skip(0).limit(50); //得到全部內容
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部門編號:"+ obj.get("deptno")+ "名稱"+obj.get("dname"));
}
}
client.close();
}
public static void main(){//3333  模糊查詢
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//設置表名
//Pattern正則的編譯 沒有構造方法,
Pattern pattern = Pattern.complie("5");//設置過濾條件,類似 like %5%
DBObject cond = new BasicDBObject();//BasicDBObject存放where條件,或者存放查詢後的數據

cond.put("dname",new BasicDBObject("$regex",pattern));//只要有json格式都是用new BasicDBObject
//設置查詢條件 如下
DBCursor cursor = col.find(cond).skip(0).limit(50);
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部門編號:"+ obj.get("deptno")+ "名稱"+obj.get("dname"));
}
}
client.close();
}
public static void main(){//44444  數據修改
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//設置表名
DBObject condA = new BasicDBObject();//BasicDBObject存放where條件,或者存放查詢後的數據,或json格式條件
condA.put("deptno",1000); //設置修改內容,deptno=1000
//condA.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));
DBObject condB = new BasicDBObject();
condB.put("$set",new BasicDBObject("dname","修改後的內容")); //修改後的內容
WriteResult result = col.update(condA,condB);//執行更新,A更新爲B
//WriteResult result = col.updateMulti(condA,condB);//修改多行 用 updateMulti
System.out.pirntln(result.getN()); //getN表示更新到的行數,存在則更新,不存在則新增。
}
client.close();
}
public static void main(){//55555  刪除數據
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//設置表名
DBObject cond = new BasicDBObject();//BasicDBObject存放where條件,或者存放查詢後的數據,或json格式條件
cond.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));
WriteResult result = col.remove(cond);//執行刪除
System.out.pirntln(result.getN()); //getN表示更新到的行數
}
client.close();
}
java 連接MongoBD操作 (基於3.x驅動)
public class Mongo3DemoA{ //1111
public static void main(){ 
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
//System.out.println(db.getCollection("deptcol").count());//獲取表deptcol集合
MongoCollection col = db.getCollection("stucol");
List<Document> all = new ArrayList<Document>();
for(int x=0 ; x<100 ; x++){
Document doc = new Document();
doc.append("sid",x);
doc.appent("name","姓名-"+x);
all.add(doc);
}
col.insertMany(all);
client.close();
}
}
public static void main(){ //22222 查詢
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
DBObject cond = new BasicDBObjcet();
cond.put("sid",new BasicDBObject("$gt",5).append("$lt",20));
MongoCursor<Document> cursor = col.find(cond).skip(5).limit(10).iterator();//跳過5,取10個
while(cursor.hasNest()){
System.out.println(cursor.next());
}
client.close();
}
public static void main(){ //33333 模糊查詢
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
Pattern pattern = Pattern.compile("10"); //like %10%
DBObject cond = new BasicDBObjcet();
cond.put("name",new BasicDBObject("$regex",pattern).append("$options","1")); //options 1不區分大小寫
MongoCursor<Document> cursor = col.find(cond).iterator();
while(cursor.hasNest()){
System.out.println(cursor.next());
}
client.close();
}
public static void main(){ //44444 數據更新
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
BasicDBObject condA = new BasicDBObject("sid",0);//數據查詢條件
BasicDBObject condA = new BasicDBObject("$set",new BasicDBObject("name","超人"));
UpdateResult result = col.updateMany(condA,condB);
System.out.pirntln(result.getMatchedCount());//取得 修改條數
client.close();
}
public static void main(){ //55555 數據刪除
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
BasicDBObject cond = new BasicDBObject("sid",0);//數據查詢條件 sid=0
DeleteResult result = new col.deleteOne();
System.out.pirntln(result.getDeletedCount());//取得 修改條數
client.close();
}
public static void main(){ //666666 統計查詢
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用戶名密碼hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
List<BasicDBObject> all = new ArrayList<BasicDBObject>();
MongoCollection col = db.getCollection("stucol");
BasicDBObject cond = new BasicDBObject(
"$group",new BasicDBObject("_id","$sex")
.append("count",new BasicDBObject("$sum",1))
.append("avg",new BasicDBObject("%avg","%salary")));//
all.add(cond);
MongoCursor<Document> cursor = col.aggregate(all).iterator();
while(cursor.hasNext()){
Cocument doc = cursor.next();
System.out.println(doc.getString("_id")+","+ doc.getInteger("count") +","+ doc.getDouble("avg"));
}
client.close();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章