博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NoSQL之【MongoDB】学习(二):DML和查询操作说明
阅读量:6200 次
发布时间:2019-06-21

本文共 16769 字,大约阅读时间需要 55 分钟。

摘要:

      操作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 --> dddmongodump  --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 = -1,alter 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(列)
**db.Test.update({"Sname":"BB"},{"$unset":{"pv_bak":1}},true,true) --删除复合条件的记录的key(列)
,第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> total21> 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)7db.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的记录多个元素查找:$alldb.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;}}}}) 返回已经更新的文档:getLastError、findAndModify> 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完成。他们的具体使用方法为:具体说明见:

group:db.collection.group(              key,              reduce,              initial,              keyf,              cond,              finalize)  mapReduce:db.collection.mapReduce(                           
,
, { out:
, query:
, sort:
, limit:
, finalize:
, scope:
, jsMode:
, verbose:
} )aggregate:使用方法见:
{ 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,具体说明见:
总平均##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大于总的平均agedb.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://mgvca.baihongyu.com/

你可能感兴趣的文章
《Oracle高性能自动化运维》一一1.4 Linux内存体系与Oracle内存空间
查看>>
《HTML5移动应用开发入门经典》—— 第1章 使用HTML5改进移动Web应用的开发
查看>>
自己动手构造编译系统:编译、汇编与链接1.1 从编程聊起
查看>>
Guava 是个风火轮之基础工具(2)
查看>>
《TensorFlow技术解析与实战》——1.3 深度学习的入门方法
查看>>
《数据分析变革:大数据时代精准决策之道》一2.1 穿越炒作的迷雾
查看>>
《嵌入式C编程:PIC单片机和C编程技术与应用》一3.5 练习
查看>>
如何在 Linux 中使用 Alpine 在命令行里访问 Gmail
查看>>
Bug:StampedLock的中断问题导致CPU爆满
查看>>
Libreoffice 4.0.3 发布 – PPA 安装源
查看>>
《Redis官方教程》Redis集群规范(二)
查看>>
《Adobe Dreamweaver CC经典教程》——1.4 选择工作区布局
查看>>
《树莓派渗透测试实战》——2.11 安装Stunnel客户端
查看>>
《操作系统真象还原》——0.4 软件是如何访问硬件的
查看>>
小技巧:检查你本地及公共 IP 地址
查看>>
《Unity 4 3D开发实战详解》一6.1 刚体
查看>>
《编写可维护的JavaScript》——第 1 章 基本的格式化 1.1缩进层级
查看>>
Linux应用总结:自动删除n天前日志
查看>>
《游戏大师Chris Crawford谈互动叙事》一9.4 谜题
查看>>
《Ansible权威指南》一1.5 Ansible通信发展史
查看>>