设为首页 收藏本站
查看: 1335|回复: 0

[经验分享] NoSQL之【MongoDB】学习(二):DML和查询操作说明

[复制链接]

尚未签到

发表于 2015-7-5 14:23:12 | 显示全部楼层 |阅读模式
  摘要:
   操作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;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
  插入:



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(=);$ne()

##select * from stu where sno > 1 and sno  1 and sno  1 and 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  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.iyunv.com/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(  
,  
,  
{  
out: ,  
query: ,  
sort: ,  
limit: ,  
finalize: ,  
scope: ,  
jsMode: ,  
verbose:   
}  
)
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.
  测试数据:


DSC0000.gif DSC0001.gif


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  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
  以上结束!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83419-1-1.html 上篇帖子: [原]分享一下我和MongoDB与Redis那些事 下篇帖子: Mongodb源码分析--Replication之OpLog
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表