NoSQL之【MongoDB】學習(二):DML和查詢操作說明


摘要:

      操作MongoDB的方法和關系型數據庫差別很大,現在對他們進行說明,后期會逐步完善。

##開頭表示MySQL
** 開頭表示MongoDB

創建:

Mongodb:文檔數據庫,擅長存非結構化數據;不需要事先規定好文檔(表)的定義。
##create table Test(……)
**db.createCollection('Test')

##drop table Test
**db.Test.drop()

##drop database test
**db.dropDatabase() 

重命名集合:

重命名表:
##rename table Test to Test_A;
**
db.Test.renameCollection('Test_A');

##create table Test_A select * from Test;
** db.Test.copyTo('Test_A') #索引沒有復制到yyy集合
**或則先備份,再還原: Test --> ddd mongodump  --host=127.0.0.1 --port=27017 -ubackup -p  --db=abc --collection=Test -o backup/ mongorestore --db=abc --collection=Test_A backup/abc/stu.bson

重命名數據庫: 

** db.copyDatabase('test','test_bak') #是一個復制,需要把原庫刪除。
{ "ok" : 1 }  

遠程復制數據庫:
db.copyDatabase(fromdb, todb, fromhost, username, password)

插入:

MongoDB插入數據時,會先把數據轉換成BSON形式傳入數據庫,再解析BSON,檢驗是否包含“_id”和文檔不超過4M大小,最后存入數據庫
##insert into Test(name) values(……)
**db.Test.insert({"name":"zhoujy"})                    --不需要事先規定好name列(鍵)
插入多個值: ##insert into Test() values(),(),()…… **db.Test.insert([{"a":1,"b":2},{"a":2,"b":3},{"a":3,"b":4}])

刪除:

刪除指定記錄
##delete from Test where name ='zhoujy'
**db.Test.remove({"name":"zhoujy"})

刪除所有記錄
##delete from Test
**db.Test.remove()

更新:

      4個參數,第一個參數是條件;第二個參數是修改器;第三個是upsert【有就更新,沒有則創建(add column)】;第四個為是否更新多行,默認是第一行。

$inc 用於int類型的key(列)加減操作,要是指定的要更新的key不存在,則會新增該key(列):
##update Test set pv=pv+1 where name ='a'alter table Test add column,
**db.Test.update({"name":"a"},{"$inc":{"pv":1}})                   --只更新第一條出現的記錄,+1
**db.Test.update({"name":"a"},{"$inc":{"pv":1}},false,true)        --更新所有符合條件的記錄,+1;(第4個參數是true)
**db.Test.update({"name":"a"},{"$inc":{"pv":-1}},false,true)       --更新所有符合條件的記錄,-1
**db.Test.update({"name":"a"},{"$inc":{"pv":-1}},true,true)        --要是更新條件找不到記錄,默認是不執行;要是第3個參數是true,則會新增一條記錄(包含條件key和被更新的key)
 $set 用於更新指定key(列),要是指定的要更新的key不存在,則會新增該key(列):
##update Test set name ='A' where pv_bak = -1alter table Test add column,
**db.Test.update({"pv_bak":-1},{"$set":{"name":"A"}})              --只更新第一條出現的記錄
**db.Test.update({"pv_bak":-1},{"$set":{"name":"A"}},false,true)   --更新所有符合條件的記錄(第4個參數是true)
**db.Test.update({"pv_bak":-11},{"$set":{"Sname":"BB"}},true,true) --要是更新條件找不到記錄,默認是不執行;要是第3個參數是true,則會新增一條記錄(包含條件key和被更新的key)

定位:可以修改內嵌文檔,用點(.)來表示內嵌文檔內的key,如:
**db.pv.update({"hit.a":1111},{"$set":{"hit.a":1}})

$unset 用於刪除指定key(列)
##alter table Test drop column ……
**db.Test.update({"Sname":"BB"},{"$unset":{"pv_bak":1}})           --刪除第一條出現的記錄的key(列)<pv_bak>
**db.Test.update({"Sname":"BB"},{"$unset":{"pv_bak":1}},true,true) --刪除復合條件的記錄的key(列)<pv_bak>,第3個參數沒有意義
**db.Test.update({},{"$unset":{"name":1}},false,true)              --刪除文檔(表)中所有name的key(列)
 $rename 用於重命名key(列)
##alter table Test change column ……
**db.Test.update({"name":"A"},{"$rename":{"nl":"age"}})            --重命名第一條出現的記錄的key(列)< nl——>age >
**db.Test.update({"name":"A"},{"$rename":{"nl":"age"}},true,true)  --重命名復合條件的記錄的key(列)< nl——>age >
**db.Test.update({},{"$rename":{"name":"Sname"}},true,true)        --重命名所有的記錄的key(列)< name——>Sname >
 更新數組操作:$push,$ne,$addToSet,$each,$pop,$pull  $push 向指定key(列)數組中最后添加數據,要是指定的key不存在,則會新增該key(列): **db.Test.update({"Sname":"A"},{"$push":{"cc":1}})                 --對符合條件的第一條出現數據的數組cc列添加一個值1(存在key),或新增數組cc,並添加值1(不存在key)
**db.Test.update({"Sname":"A"},{"$push":{"cc":1}},false,true)      --對符合條件的數據的數組cc列添加一個值1(存在key),或新增數組cc,並添加值1(不存在key)
**db.Test.update({},{"$push":{"dd":"a"}},false,true)               --對所有文檔(表)的數組cc列添加一個值1(存在key),或新增數組cc,並添加值1(不存在key)
 $ne 判斷是否存在,會出現重復情況,條件不一樣,一樣的值也能插入: **db.Test.update({"ee":{"$ne":"A"}},{"$push":{"ee":"A"}})           --第一條出現是否存在數組ee中A的元素,值不存在則添加(push)A,ee不存在則新增key(列)
**db.Test.update({"ee":{"$ne":"B"}},{"$push":{"ee":"A"}})           --第一條出現是否存在數組ee中B的元素,值不存在則添加(push)A,ee不存在則新增key(列),和上面一條導致ee元組有2個A元素,出現重復元素
**db.Test.update({"ee":{"$ne":"B"}},{"$push":{"ee":"A"}},true,true) --對所有數據(第4個參數,第3個參數無效),是否存在數組ee中A的元素,值不存在則添加(push)A,ee不存在則新增key(列)
 $addToSet 判斷是否存在,不會出現重復情況: **db.Test.update({"name":"a"},{"$addToSet":{"email":"asd"}})
**db.Test.update({"age":"13"},{"$addToSet":{"email":"asd"}})           --以上2個條件對應同一條記錄,但是同樣的值寫入數組只能記錄一次,不會重復
**db.Test.update({"app":"13"},{"$addToSet":{"email":"asd"}},true)      --第三個參數,讓條件中找不到的記錄得到新增一個key(列)
**db.Test.update({"name":"a"},{"$addToSet":{"email":"asd"}},true,true) --第四個參數,讓匹配到的記錄都得到更新
**db.Test.update({},{"$addToSet":{"email":"asd"}},true,true)           --更新所有記錄
 $addToSet + $each 為數組添加多個元素: **db.Test.update({"name":"a"},{"$addToSet":{"xyz":{"$each":["a","b","c"]}}})   --更新復合條件的第一條出現
**db.Test.update({},{"$addToSet":{"add":{"$each":["a","b","c"]}}},true,true)   --更新所有記錄
 $pop、$pull 刪除數組中的元素:
位置: **db.Test.update({"name":"a"},{"$pop":{"cc":1}})                        --第一條出現刪除數組cc的最后一個元素
**db.Test.update({"name":"a"},{"$pop":{"cc":-1}})                       --第一條出現刪除數組cc的第一個元素
**db.Test.update({"name":"a"},{"$pop":{"cc":-1}},false,true)            --符合條件的全部數據刪除數組cc的第一個元素
**db.Test.update({},{"$pop":{"cc":-1}},false,true)                      --全部數據刪除數組cc的第一個元素
指定:
**db.Test.update({"name":"b"},{"$pull":{"cc":4}})                       --第一條出現刪除數組cc的指定的元素4
**db.Test.update({"name":"a"},{"$pull":{"cc":4}},false,true)            --符合條件的全部數據刪除數組cc的指定元素4
**db.Test.update({},{"$pull":{"cc":4}},false,true)                      --全部數據刪除數組cc的指定元素4
 定位修改 $點(.)+ 位置(數字)來表示數組內部的key,如:
**db.Test.update({"age":14},{"$inc":{"ddd.0.a":10}})                    --更新數組ddd的第一個元素(0)的a鍵的值,需要知道a鍵(列)在數組的第幾個元組里
**db.Test.update({"ddd.a":1},{"$set":{"ddd.$.d":20}})                   --根據條件(數組ddd里a=1的條件),去更新最先出現的符合要求的數組的d鍵,不需要知道被更新的key在第幾個位置
第三和第四參數效果和上面一樣

普通查詢:

##select * from stu 
**db.stu.find()
條件查詢:
##select * from stu where sno = 8
**db.stu.find({"sno":8})
**db.stu.find({"sno":{"$in":[8]}}) 

##select * from stu where sno = 1 and sname ='ABC'
**db.stu.find({"sno":1,"sname":"ABC"})
in查詢:
##select * from stu where sno in (1,3,5,8)
**db.stu.find({"sno":{"$in":[1,3,5,8]}})
not in 查詢:
##select * from stu where sno not in (1,3,5,8)
**db.stu.find({"sno":{"$nin":[1,3,5,8]}})
or 查詢:
##select * from stu where sno = 5 or sname ='zhoujy'
**db.stu.find({"$or":[{"sno":5},{"sname":"zhoujy"}]})

##select * from stu where sno in (1,2,3) or sname ='zhoujy'
**db.stu.find({"$or":[{"sno":{"$in":[1,2,3]}},{"sname":"zhoujy"}]})

##select * from stu where sno = 4 and sname ='zhoujy' or sno = 1
**db.stu.find({"$or":[{"sno":4,"sname":"zhoujy"},{"sno":1}]})

##select sno,sname from stu where sno =2
**db.stu.find({"sno":2},{"sno":1,"sname":1,"_id":0})

##select count(*) from stu where sno=1
**db.stu.find({"sno":1}).count()

不等條件查詢: $lt(
<);$lte(<=);$gt(>);$gte(>=);$ne(<>)
##
select * from stu where sno > 1 and sno <=5 **db.stu.find({"sno":{"$gt":1,"$lte":5}}) ##select * from stu where sno > 1 and sno <=5 and sno <> 3 **db.stu.find({"sno":{"$gt":1,"$lte":5,"$ne":3}}) ##select * from stu where sno > 1 and sno <=5 and sname <> 'zhoujy' **db.stu.find({"sno":{"$gt":1,"$lte":5},"sname":{"$ne":"zhoujy"}})
取余:
##select sno,sname from stu where sno%5 = 1
**db.stu.find({"sno":{"$mod":[5,1]}},{"sno":1,"sname":1,"_id":0})

##select sno,sname from stu where sno%5 != 1
**db.stu.find({"sno":{"$not":{"$mod":[5,1]}}},{"sname":1,"sno":1,"_id":0})

匹配查詢: ##
select sno,sname from stu where sname like '%j%' **db.stu.find({"sname":/j/},{"sno":1,"sname":1,"_id":0}) --區分大小寫 **db.stu.find({"sname":/j/i},{"sno":1,"sname":1,"_id":0}) --不區分大小寫 ##select sno,sname from stu where sname like 'j%' **db.stu.find({"sname":/^j/},{"sno":1,"sname":1,"_id":0}) --區分大小寫 **db.stu.find({"sname":/^j/i},{"sno":1,"sname":1,"_id":0}) --不區分大小寫 ##select sno,sname from stu where sname like '%j' **db.stu.find({"sname":/j$/},{"sno":1,"sname":1,"_id":0}) --區分大小寫 **db.stu.find({"sname":/j$/i},{"sno":1,"sname":1,"_id":0}) --不區分大小寫
限制查詢: ##select sno,sname from stu limit 3 **db.stu.find({},{"sno":1,"sname":1,"_id":0}).limit(3) ##select sno,sname from stu where sno > 3 limit 3 **db.stu.find({"sno":{"$gt":3}},{"sno":1,"sname":1,"_id":0}).limit(3) ##select sno,sname from stu where sno=102 limit 3 **db.stu.find({"sno":102},{"sno":1,"sname":1,"_id":0}).limit(3)
排序查詢: ##
select sno,sname from stu order by sno **db.stu.find({},{"sno":1,"sname":1,"_id":0}).sort({"sno":1})
##select sno,sname from stu order by sno,sname
**db.stu.find({},{"sno":1,"sname":1,"_id":0}).sort({"sno":1,"sname":1})

##select sno,sname from stu order by sno,sname desc **db.stu.find({},{"sno":1,"sname":1,"_id":0}).sort({"sno":1,"sname":-1})
##select sno,sname from stu order by sno desc 
**db.stu.find({},{"sno":1,"sname":1,"_id":0}).sort({"sno":-1})

##
select sno,sname from stu where sno <=3 order by sno desc
**db.stu.find({"sno":{"$lte":3}},{"sno":1,"sname":1,"_id":0}).sort({"sno":-1})

##
select sno,sname from stu where sno <=10 order by sno desc limit 4
**db.stu.find({"sno":{"$lte":10}},{"sno":1,"sname":1,"_id":0}).sort({"sno":-1}).limit(4) --limit 和 sort 沒有先后順序,放前放后結果一樣

重定位查詢: ##select sno,sname from stu limit 4,無窮大 **db.stu.find({},{"sno":1,"sname":1,"_id":0}).skip(4) --從第5行開始到最后 ##select sno,sname from stu where sno <=10 limit 4,3 **db.stu.find({"sno":{"$lte":10}},{"sno":1,"sname":1,"_id":0}).skip(4).limit(3) --從第5行開始,取3行 ##select sno,sname from stu where sno <=10 order by sno desc limit 4,3 **db.stu.find({"sno":{"$lte":10}},{"sno":1,"sname":1,"_id":0}).limit(3).sort({"sno":-1}).skip(4) --sort,skip,limit 這3個操作沒有順序,放哪里都一樣
去重查詢: ##select distinct a from Test **db.Test.distinct("a") ##select distinct a from Test where a>2 **db.Test.distinct("a",{"a":{"$gt":1}}) 隨機選取: ##select sno,sname from stu order by rand() limit 10 **通過skip(random)來取得隨機數 > total = db.stu.count() 21 > total 21 > total = db.stu.count() 21 > random = Math.floor(Math.random()*total) 16 > random = Math.floor(Math.random()*total) 1 > random = Math.floor(Math.random()*total) 7 db.stu.find({"sno":{"$lte":10}},{"sno":1,"sname":1,"_id":0}).limit(10).sort({"sno":-1}).skip(random)

Mongodb 特有:

null值查詢:
null
,列出Z鍵(列)是NULL,並且列出不存在Z鍵(列)的記錄 db.stu.find({"Z":null}) 列出存在Z鍵(列),並且Z鍵(列)是NULL的記錄 db.stu.find({"Z":{"$in":[null],"$exists":true}}) 數組查詢: 查找一個元素 db.food.find({"fruit":"a"}) <==> db.food.find({"fruit":{"$all":["a"]}}) --查找fruit數組里包含a的記錄 多個元素查找:$all db.food.find({"fruit":{"$all":["a","b"]}}) --查找fruit數組里包含a,b的記錄,順序不影響 指定數組里的位置 db.food.find({"fruit.2":"c"}) --查找fruit數組里第3個位置是c的記錄 指定數組的長度 db.food.find({"fruit":{"$size":5}}) --查找fruit數組長度是5的記錄 取數組的前/后3個子集 db.food.find({"fruit":"X"},{"fruit":{"$slice":3}}) --查找fruit數組里包含X記錄,並返回數組的前3位 db.food.find({"fruit":"X"},{"fruit":{"$slice":-3}}) --查找fruit數組里包含X記錄,並返回數組的后3位 db.food.find({"fruit":"X"},{"fruit":{"$slice":[3,2]}}) --查找fruit數組里包含X記錄,並返回從數組位子3開始的后2位 db.food.find({},{"fruit":{"$slice":3}}) --查找fruit數組,並返回從數組的前3位
db.food.find({"fruit":{"$exists":true}},{"fruit":{"$slice":-1}}) --查找fruit數組存在,並返回數組的最后一位
 文檔查詢:
指定內嵌文檔里的鍵:點連接
db.post.find({"xx.age":12})                            --查找內嵌文檔xx,找出age是12的記錄
db.post.find({"xx.age":12,"xx.add":"hz","xx.sex":1})   --查找內嵌文檔xx,找出age是12,add是hz,sex是1的記錄
db.post.find({"xx.add":"hz","xx.age":{"$gt":12}})      --查找內嵌文檔xx,找出add是hz,age > 12 的記錄,$elemMatch
 列出全部內容:如果鍵增加,或順序不一樣,則查不出來
db.post.find({"xx":{"sex":1,"add":"hz","age":12}})     --查找內嵌文檔xx,完全匹配
 $where 查詢:
普通列: ##注意格式,查找出2個鍵的值相等的文檔:{"D" :
4, "E" : 4, "F" : 5 },D,E相等 db.foo.find({"$where":function(){ ##固定格式 for (var numA in this){ ##賦值該文檔的key給一個變量,this 表示該文檔 for (var numB in this){ ##賦值該文檔的key給一個變量 if (numA != numB && this[numA] == this[numB]) ##判斷,key不相等但他們的值相等,即D和D不能比 return true; ##返回 } } } }) ##注意格式,查找出至少2個值大於5的文檔 db.foo.find({"$where":function(){ ##固定格式 var cnt = 0; ##聲明變量 for (var num in this){ ##賦值該文檔的key給一個變量,this 表示該文檔 if (this[num] >=5) ##判斷,如果值大於5,則... cnt++; } return cnt >=2; ##當cnt>=2,返回 } }) 內嵌文檔: ##注意格式,查找出至少2個值大於90的文檔 db.stu.find({"$where":function(){ var cnt = 0; for (var num in this.course){ if( this.course[num] > 90) cnt++; } return cnt >=2; } }) ##注意格式,查找出2個鍵的值相等的文檔 db.stu.find({"$where":function(){ for (var t1 in this.course){ for (var t2 in this.course){ if(t1 != t2 && this.course[t1]==this.course[t2]) return true; } } } })

返回已經更新的文檔:getLastErrorfindAndModify
> db.runCommand({getLastError:1}) --開啟 { "updatedExisting" : true, "n" : 1, --修改的行數 "connectionId" : 1, "err" : null, "ok" : 1 } ##只返回被改動的記錄 > db.Test.findAndModify({ ... "query":{"name":"b"}, --條件 ... "update":{"name":"BB"}, --更新 ... "new":true --返回修改后的數據 ... }) > db.Test.findAndModify({ ... "query":{"name":"b"}, ... "update":{"name":"BB"}, ... "new":false --返回修改前的數據 ... })

聚合函數操作:{count,sum,max,min,avg}可以通過:group、mapreduce、aggregate完成。他們的具體使用方法為:具體說明見:
http://blog.csdn.net/huntzw/article/details/8669986
http://cn.docs.mongodb.org/manual/reference/command/nav-aggregation/

group:
db.collection.group(  
            key,  
            reduce,  
            initial,  
            keyf,  
            cond,  
            finalize)  

mapReduce: db.collection.mapReduce(  
                         <mapfunction>,  
                        <reducefunction>,  
                         {  
                           out: <collection>,  
                           query: <document>,  
                           sort: <document>,  
                           limit: <number>,  
                           finalize: <function>,  
                           scope: <document>,  
                           jsMode: <boolean>,  
                           verbose: <boolean>  
                         }  
                       )

aggregate: 使用方法見:http://blog.nosqlfan.com/html/3648.html
{ aggregate: "[collection]", pipeline: [pipeline] }
Pipeline 定義的操作有:
$match – query predicate as a filter.
$project – use a sample document todetermine the shape of the result.
$unwind – hands out array elements oneat a time.
$group – aggregates items into bucketsdefined by a key.
$sort sort document.
$limit – allow the specified number ofdocuments to pass
$skip – skip over the specified numberof documents.

測試數據:

db.test_gh.insert([{"_id":1,"name":"a","age":11,"dept":111},{"_id":2,"name":"b","age":12,"dept":111},{"_id":3,"name":"c","age":13,"dept":222},{"_id":4,"name":"d","age":14,"dept":222},{"_id":5,"name":"e","age":15,"dept":111},{"_id":6,"name":"f","age":16,"dept":111}])
View Code
##select dept,count(*) from test_gh group by dept

**db.test_gh.group({
'key':{"dept":1},                  /* group by dept */
'reduce':function(obj,prev){
prev.ccount ++                     /* count(*) */
},
'initial':{"ccount":0}             /*初始化變量*/
})
[ { "dept" : 111, "ccount" : 4 }, { "dept" : 222, "ccount" : 2 } ]

##select dept,sum(age) from test_gh group by dept

**db.test_gh.group({
"key":{"dept":1},
"reduce":function(obj,prev){
prev.ssum += obj.age               /*obj表示集合(表)里的文檔(行)*/
},
"initial":{"ssum":0}
})
[ { "dept" : 111, "ssum" : 54 }, { "dept" : 222, "ssum" : 27 } ]

##select dept,max(age) from test_gh group by dept;

**db.test_gh.group({
"key":{"dept":1},
"reduce":function(obj,prev){
if (obj.age > prev.age){            /*計算出最大值*/
prev.age = obj.age             
}
},
"initial":{"age":0}                 /*初始化一個變量*/
})
[ { "dept" : 111, "age" : 16 }, { "dept" : 222, "age" : 14 } ]

##select dept,min(age) from test_gh group by dept

**db.test_gh.group({
"key":{"dept":1},
"reduce":function(obj,prev){
if(obj.age < prev.age){             /*計算出最小值*/
prev.age=obj.age}
},
"initial":{"age":9999999}           /*初始化一個變量,給出一個大於最大的數*/
})
[ { "dept" : 111, "age" : 11 }, { "dept" : 222, "age" : 13 } ]


mapreduce方法也可以實現,2.1之后出現一個新的聚合用的函數:aggregate

使用aggregate,具體說明見:http://my.oschina.net/GivingOnenessDestiny/blog/88006
總平均
##select avg(age) from test_gh   
**db.test_gh.aggregate({"$group":{_id:null,Avg:{"$avg":"$age"}}}).result[0].Avg /*_id是一個需要被group的key,null表示沒有group,里面的都帶 “$” */
13.5 部門平均 ##select avg(age) from test_gh group by dept **db.test_gh.aggregate({"$group":{_id:"$dept",Avg:{"$avg":"$age"}}}).result/*_id是一個需要被group的key,$dept表示沒有group dept,里面的都帶 “$” */
[ {
"_id" : 222, "Avg" : 13.5 }, { "_id" : 111, "Avg" : 13.5 } ] ##select dept,avg(age) from test_gh where name <'e' group by dept $match 相當與一個query條件 **db.test_gh.aggregate({"$match":{"name":{"$lt":"e"}}},{"$group":{_id:"$dept",Avg:{"$avg":"$age"}}}) 部門的平均age大於總的平均age db.test_gh.aggregate([ {$group :{_id:"$dept",Avg:{"$avg":"$age"}}}, /*部門的平均*/ {$match :{Avg:{"$gt": /*比較*/ db.test_gh.aggregate({ $group :{_id:null,totalAvg:{"$avg":"$age"}}}).result[0].totalAvg /*總的平均,一個aggregate*/ }}} ]).result [ { "_id" : 111, "Avg" : 13.8 } ] aggregate 實現其他的聚合: 比如最大最小: > db.test_gh.aggregate({$group:{_id:"$dept",Avg:{"$min":"$age"}}}).result [ { "_id" : 222, "Avg" : 13 }, { "_id" : 111, "Avg" : 11 } ] > db.test_gh.aggregate({$group:{_id:"$dept",Avg:{"$max":"$age"}}}).result [ { "_id" : 222, "Avg" : 14 }, { "_id" : 111, "Avg" : 16 } ]

更多的聚合函數信息見:
http://cn.docs.mongodb.org/manual/reference/command/nav-aggregation/
http://www.infoq.com/cn/articles/implementing-aggregation-functions-in-mongodb

 

備份:

http://weizhifeng.net/backup-and-restore-data-of-mongodb.html

以上結束!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM