MongoDB基本使用
基本概念
- 数据库
MongoDB的一个实例可以拥有一个或多个相互独立的数据库,每个数据库都有自己的集合(表)。 - 集合
集合可以看作是拥有动态模式的表 - 方档
文档是MongoDB中基本的数据单元,类似于RDB的行。文档是键值对的一个有序集合。在JS中,文档被表示成对象。 - _id
每个文档都有个特殊的_id
,在文档所属集合中是唯一的,默认由mongodb自己维护,当然你也可以自己指定。 - JavaScript shell
MongoDB自带了一个功能强大的JavaScript Shell,可以用于管理或操作MongoDB - MongoDB和RDB的概念对比
- 都有数据库的概念
- 集合 –>RDB的表
- 文档 –>RDB表中的一条记录
- 文档对象里面的 key –> RDB表中的字段
- 文档对象里面的 value–> RDB表中字段的值
- MongoDB中没有外键的概念
1:不能是空串 2:不得含有/、\、?、$、空格、空字符等等,基本只能使用ASCII中的字母和数字 3:区分大小写,建议全部小写 4:最多为64字节 5:不得使用保留的数据库名,比如:admin,local,config
注意:数据库最终会成为文件,数据库名就是文件的名称
1:不能是空串 2:不能包含\0字符(空字符),这个字符表示集合名的结束,也不能包含”$” 3:不能以”system.”开头,这是为系统集合保留的前缀
1:不能包含\0字符(空字符),这个字符表示键的结束 2:“.”和“$”是被保留的,只能在特定环境下用 3:区分类型,同时也区分大小写 4:键不能重复
注意:文档的键值对是有顺序的,相同的键值对如果有不同顺序的话,也是不同的文档
数据类型 | 描述 | 举例 |
---|---|---|
null | 表示空值或者未定义的对象 | {“x”:null} |
布尔值 | 真或者假:true或者false | {“x”:true} |
32位整数 | shell不支持该类型,默认会转换成64位浮点数,也可以使用NumberInt类 | {“x”:NumberInt(“3”)} |
64位整数 | shell不支持该类型,默认会转换成64位浮点数,也可以使用NumberLong类 | {“x”:NumberLong(“3”)} |
64位浮点数 | shell中的数字就是这一种类型 | {“x”:3.14,”y”:3} |
字符串 | UTF-8字符串 | {“foo”:”bar”} |
符号 | shell不支持,shell会将数据库中的符号类型的数据自动转换成字符串 | |
对象id | 文档的12字节的唯一id | {“id”: ObjectId()} |
日期 | 从标准纪元开始的毫秒数 | {“date”:new Date()} |
正则表达式 | 文档中可以包含正则表达式,遵循JavaScript的语法 | {“foo”:/foobar/i} |
代码 | 文档中可以包含JavaScript代码 | {“x”:function() {}} |
未定义 | undefined | {“x”:undefined} |
数组 | 值的集合或者列表 | {“arr”: [“a”,”b”]} |
内嵌文档 | 文档可以作为文档中某个key的value | {“x”:{“foo”:”bar”}} |
接下来我在命令行客户端中操作数据,这里假设你已经进入命令行【一般执行mongo即可】。
# 运行shell,命令:mongo ip:port,在这里我使用的默认的端口所以就没有指定[root@bogon mongodb-linux-x86_64-rhel70-3.4.1]# ./bin/mongo# 显示现有的数据库,命令:show dbs;> show dbsadmin 0.000GBlocal 0.000GB# 显示当前使用的数据库,命令:db> dbtest# 切换当前使用的数据库,命令:use 数据库名称> use localswitched to db local# 创建数据库:MongoDB没有专门创建数据库的语句,可以使用“use” 来使用某个数据库,如果要使用的数据库不存在,那么将会创建一个,会在真正向该库加入文档后,保存成为文件。> use mallswitched to db mall# 删除数据库,命令:db.dropDatabase(),在使用这个命令前要记得切换到将被删除的数据,可以用上面学到的命令确认一下。> dbmall> db.dropDatabase(){ “dropped” : “mall”, “ok” : 1 }# 显示现有的集合,命令:show collections,我们切换到一个新的数据库,到里面插入一个集合并保存一条数据,这样做只是为了造些语句便于演示这个命令。> use mallswitched to db mall> db.user.insert({name:‘张三’})WriteResult({ “nInserted” : 1 })> show collectionsuser# 创建集合:在MongoDB中不用创建集合,因为没有固定的结构,直接使用db.集合名称.命令 来操作就可以了。如果非要显示创建集合的话,用:db.createCollecion(‘集合名称’);> db.createCollection(‘system’){ “ok” : 1 }# 插入并保存文档# insert方法,可以单独插入一个文档,也可以插入多个,用“[ ]”即可。注意:# 1:MongoDB会为每个没有“_id”字段的文档自动添加一个”_id”字段# 2:每个Doc必须小于16MB# 上面已经有演示,这里就不再赘述# 删除文档,命令:remove , 可以按条件来删除只是删除文档,集合还在,如果使用 drop命令,会连带集合和索引都删掉# 查看集合中所有的文档,命令:db.集合名称.find();> db.user.find(){ “_id” : ObjectId(“5871e5f99423674edcea4eec”), “name” : “张三” }> db.user.remove({})WriteResult({ “nRemoved” : 1 })> db.user.find()># 查看集合的状态信息:db.集合名.stats();> db.user.stats(){“ns” : “mall.user”,“size” : 0,“count” : 0,“storageSize” : 20480,“capped” : false,“wiredTiger” : {…},…}# 查看集合中第一个文档,命令:db.集合名称.findOne({条件对象}),造一些数据方便测试> db.user.insert([{name:‘李四’},{name:‘王五’}])BulkWriteResult({“writeErrors” : [ ],“writeConcernErrors” : [ ],“nInserted” : 2,“nUpserted” : 0,“nMatched” : 0,“nModified” : 0,“nRemoved” : 0,“upserted” : [ ]})> db.user.findOne(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }# 文档替换,命令: db.集合名称. update(条件,新的文档);> db.user.update({name:‘王五’}, {name:‘王五’,sex:‘男’})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }{ “_id” : ObjectId(“5871e8fe9423674edcea4eee”), “name” : “王五”, “sex” : “男” }# 上面的操作说明:先找到名称是王五的这一条记录,然后用新文档替换数据原来的所有值,是一个整体替换的操作。# save方法# 如果文档存在就更新,不存在就新建,主要根据”_id”来判断。可以看到我们插入了一个名称相同的文档,结果是成功的。> db.user.save({name:‘李四’})WriteResult({ “nInserted” : 1 })> db.user.find(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }{ “_id” : ObjectId(“5871e8fe9423674edcea4eee”), “name” : “王五”, “sex” : “男” }{ “_id” : ObjectId(“5871eb8e9423674edcea4eef”), “name” : “李四” }# upsert# 找到了符合条件的文档就更新,否则会以这个条件和更新文档来创建一个新文档。指定update方法的第三个参数为true,可表示是upsert> db.user.update({name:“张三”}, {name:“张三”,sex:‘女’})WriteResult({ “nMatched” : 0, “nUpserted” : 0, “nModified” : 0 })> db.user.find(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }{ “_id” : ObjectId(“5871e8fe9423674edcea4eee”), “name” : “王五”, “sex” : “男” }{ “_id” : ObjectId(“5871eb8e9423674edcea4eef”), “name” : “李四” }# 上面的修改没有成功,原因就在于根据条件查询不到张三这个文档,那下面我们给他换上第三个参数。我们希望找不到就增加,找到就修改。> db.user.update({name:“张三”}, {name:“张三”,sex:‘女’}, true)WriteResult({“nMatched” : 0,“nUpserted” : 1,“nModified” : 0,“_id” : ObjectId(“5871ecba7f264dfcaeec2489”)})> db.user.find(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }{ “_id” : ObjectId(“5871e8fe9423674edcea4eee”), “name” : “王五”, “sex” : “男” }{ “_id” : ObjectId(“5871eb8e9423674edcea4eef”), “name” : “李四” }{ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “女” }#大家请看上面的操作,从查询出来的结果中我们看到,要修改的记录没有找到就变成新增操作了。# 查询更新了多少个文档# 使用命令:getLastError ,返回最后一次操作的相关信息,里面的n就是更新的文档的数量。> db.runCommand({“getLastError”:1}){“connectionId” : 3,“n” : 0,“syncMillis” : 0,“writtenTo” : null,“err” : null,“ok” : 1}
更新修改器,用来做复杂的更新操作
细心的人可能已经发现,上面介绍的修改操作是整体替换的,如果想局部修改怎么办呢?这节就告诉你具体的方法。
# 我准备了测试数据如下> db.user.find(){ “_id” : ObjectId(“5871e8fe9423674edcea4eed”), “name” : “李四” }{ “_id” : ObjectId(“5871e8fe9423674edcea4eee”), “name” : “王五”, “sex” : “男” }{ “_id” : ObjectId(“5871eb8e9423674edcea4eef”), “name” : “李四” }{ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “女” }# 1:$set :指定一个字段的值,如果字段不存在,会创建一个> db.user.update({name:‘张三’}, {$set:{sex:‘保密’}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密” }# 如果指定修改的字段不存在则新增加> db.user.update({name:‘张三’}, {$set:{nick:‘小三’}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “nick” : “小三” }# 2:$unset :删掉某个字段> db.user.update({name:‘张三’}, {$unset:{nick:1}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密” }# 3:$inc :用来增加已有键的值,如果字段不存在,会创建一个。只能用于整型、长整型、或双精度浮点型的值。> db.user.update({name:‘张三’}, {$inc:{age:12}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12 }# 4:$push:向已有数组的末尾加入一个元素,要是没有就新建一个数组> db.user.update({name:‘张三’}, {$set:{group:[4,2]}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 4, 2 ] }> db.user.update({name:‘张三’}, {$push:{group:5}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 4, 2, 5 ] }# 5:$each:通过一次$push来操作多个值,同时push多个值> db.user.update({name:‘张三’}, {$push:{group:{$each:[4,2,6,5]}}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 4, 2, 5, 4, 2, 6, 5 ] }# 6:$slice:限制数组只包含最后加入的n个元素,其值必须是负整数> db.user.update({name:‘张三’}, {$push:{group:{$each:[4,2,6,5],$slice:-3}}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 2, 6, 5 ] }# 7:$sort:对数组中的元素,按照指定的字段来对数据进行排序(1为升序,-1为降序),然后再按照slice删除。注意:不能只将$slice或者$sort与$push配合使用,且必须使用$each> db.user.update({name:‘张三’}, {$push:{group:{$each:[4,2,6,5],$slice:-3, $sort:1}}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 6 ] }# 8:$ne:判断一个值是否在数组中,如果不在则添加进去> db.user.update({name:‘张三’, group:{$ne:7}}, {$push:{group:7}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 6, 7 ] }> db.user.update({name:‘张三’, group:{$ne:7}}, {$push:{group:7}})WriteResult({ “nMatched” : 0, “nUpserted” : 0, “nModified” : 0 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 6, 7 ] }# 9:$addToSet:将数组作为数据集使用,以保证数组内的元素不会重复> db.user.update({name:‘张三’}, {$addToSet:{group:7}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 0 })# 10:$pop :从数组一端删除元素,{$pop:{key:1}},从末尾删掉一个,-1则从头部删除> db.user.update({name:‘张三’}, {$pop:{group:1}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })# 11:$pull:按照条件来删除所有匹配的元素> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 6, 7, 7 ] }> db.user.update({name:‘张三’}, {$pull:{group:7}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 6 ] }# 12:$:用来修改第一个匹配的元素> db.user.update({name:‘张三’}, {$set:{‘group.2’:8}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 6, 8 ] }# 像上面这种就是根据数组的索引来替换值> db.user.update({name:‘张三’, ‘group.1’:6}, {$set:{‘group.$’:4}})WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })> db.user.find({name:‘张三’}){ “_id” : ObjectId(“5871ecba7f264dfcaeec2489”), “name” : “张三”, “sex” : “保密”, “age” : 12, “group” : [ 5, 4, 8 ] }
细心的人可能已经发现,上面介绍以上的命令一定要自己都跟着练习几次,如此这些东西才能算是你学到的。学了和学到是两个完全不同的状态。我后面还会进一步介绍其它高级内容,以及与实际项目的结合,欢迎关注。
来源:http://blog.csdn.net/xiaoxing598/article/details/54233044