MongoDB从零开始

  • MongDB是什么?

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongDB不是传统的关系型数据库(mysql、oracle等等)。MongoDB是非关系型数据库。那么非关系型数据库存储的是什么?有些存储的是键值对数据比如redis;有些存储的是数据列组比如cassandra;有些存储的是对象objecttivity/DB,还有些存储的是图形关系比如neo4j。而MongoDB存储的则是文档,MongoDB就是存储文档的非关系型数据库,是一个面向文档的免费数据库,多用于数据采集和分散处理,特别是在大数据处理方面比较擅长。
MongoDB数据库的结构。一个MongoDB数据库中可以看到很多集合。拥有相似内容的文档被归类到同一个集合之下,而每一个文档中包含各种各样的字段以及他们对应的值。MongoDB支持的是一种JSON的扩展格式,成为bson,只要理解MongoDB存储json就够了。同一个集合里面的文档可以拥有完全不同的字段。比如:可以把描述用户信息的文档和描述用户账户信息的文档放在同一个集合里。在MongoDB里并不存在一个提前制定好的数据格式,所以比较灵活。

  • MongoDB基本概念的理解

MongoDB和关系数据库一对一的理解:
数据库(Database) -> 数据库(Database)
集合(Collection) -> 数据表(Table)
文档(Document) -> 记录(Record)

  • MongoDB使用步骤

1、建立数据库(MyData)
2、建立数据集合(Article(文章集合)、Comment(评论集合)、Author(作者集合)…)
3、建立数据

 - MyData(数据库)
	- Article(集合)
		- {"_id":"1","title":"学习MongoDB"......}(记录)
		- {"_id":"2","title":"学习Redis","bsflag":"1"......}(每个记录的字段可以不同,更加灵活)
		- {"_id":"3","title":"学习Oracle"......}
		- ......
	- Comment(集合)
		- {"_id":"1","content":"点赞"......}(记录)
		- {"_id":"2","content":"学习"......}
		- {"_id":"3","content":"好评"......}
		- ......
	- Author(集合)
		- {"_id":"1","user":"赵山河"......}(记录)
		- {"_id":"2","user":"刘海柱"......}
		- {"_id":"3","user":"赵红兵"......}
		- ......
  • MongoDB的安装
    略。网上有很多win和linux的安装教程。
  • MongoDB命令行工具
> help; 帮助
> show dbs; 查看所有数据库
> use MyData; 切换到数据库,有则切换,无则创建
> show collections; 查看所有集合
> db.createCollection("Article"); 创建集合
> db.createCollection("Comment"); 创建集合
> db.createCollection("Author"); 创建集合
> db.dropDatabase(); 删除数据库(先切换进来再删除)
> db.stats(); 数据库参数

在这里插入图片描述在这里插入图片描述

  • MongoDB数据集合的操作
> show dbs;
> use MyData; 切换到数据库
> show collections; 查看该数据库下的所有集合
> db.createCollection("users"); 创建users集合
> db.users.find(); 相当于select
> db.users.renameCollection("user_info"); 使用db.集合名(users).renameCollection来更改集合名称
> db.user_info.drop(); db.集合名,删除该集合
  • MongoDB操作文档

文档相当于关系型数据库里的数据记录。

> use MyData; 切换到数据库
> db.createCollection("Article"); 创建集合
> db.Article.insert(
... {
... title:"MongoDB的第一篇文章",
... content:"这里是文章内容。"
... }
... );  插入,这里使用分号来结束插入,没打分号之前直接回车会跳到下一行继续输入。
> db.Article.find(); 查询Article集合下所有文档,输出如下:
{ "_id" : ObjectId("5d0e47c96b39abb8369c9851"), "title" : "MongoDB的第一篇文章", "content" : "这里是文章内容。" }
这里的_id,为MongoDB默认给分配的不需要管它,当然它也是唯一的。继续插入:
> db.Article.insert(
... {
... title:"MongoDB的第二篇文章",
... content:"这里依然是文章内容。",
... tag:["未分类"]
... }
... );
这里多插入了一个tag,MongoDB每条记录的字段可以不一样,这样就更加灵活了。
> db.Article.find(); 查询Article集合下所有文档,输出如下:
{ "_id" : ObjectId("5d0e47c96b39abb8369c9851"), "title" : "MongoDB的第一篇文章", "content" : "这里是文章内容。" }
{ "_id" : ObjectId("5d0e49856b39abb8369c9853"), "title" : "MongoDB的第二篇文章", "content" : "这里依然是文章内容。", "tag" : [ "未分类" ] }
可以看到每个ID是不一样的,这个无需我们担心。第二篇文档多了一个tag字段也显示出来了。
> db.Article.count(); 查询Article集合下文档条数
> db.Article.remove({}); 删除Article集合下所有文档。{}中是可以写条件的,这里是空的是删除所有。
  • MongoDB带条件查询文档
db.Article.find({"",""}); find里写条件,格式为json。
符号:$gte(大于等于),$gt(大于),$lte(小于等于),$lt(小于),$eq(等于),$ne(不等于)
正则表达式:/k/,/^k/
db.Article.distinct("field_name"); 字段去重

查询测试:

> db.Article.insert({title:"MongoDB从入门到放弃",rank:2,tag:"study"}); 创建文档。
> db.Article.insert({title:"java从入门到放弃",rank:1,tag:"study"});
> db.Article.insert({title:"CentOS的安装",rank:3,tag:"it"});
> db.Article.insert({title:"中国开发者应多关注以太坊",rank:4,tag:"it"});
> db.Article.insert({title:"英雄联盟自走棋火爆上线",rank:5,tag:"game"});
> db.Article.insert({title:"刀塔2自走棋手游上线",rank:6,tag:"game"});
> db.Article.find({tag:"game"}); 查询tag字段为game的文档
> db.Article.find({rank:{$gte:4}}); 查询rank字段大于等于4的文档
> db.Article.find({rank:{$lt:4}}); 查询rank字段小于4的文档
> db.Article.find({title:/java/}); 查询title字段包含java的文档(使用正则)
> db.Article.find({title:/^M/}); 查询title字段以M开头的文档(使用正则)
> db.Article.distinct("tag"); 去重,查看有几种tag。结果:[ "study", "it", "game" ]
  • MongoDB复杂条件查询文档
> db.Article.find({"":"","":""}); db.集合名,find中多条件
> db.Article.find({$or:[{...},{...}]}); 与或非
> db.Article.find({"":{$in:[...]}}); 与关系型数据库的in相同
> db.Article.find({"",{$exists:true}}); 当文档的某个字段存在时

查询测试:

> db.Article.find({title:/M/,"rank":{$gte:1}}); 查询标题中包含M并且rank大于等于1的文档
> db.Article.find({$or:[{title:/M/},{rank:{$gte:3}}]}); 查询标题包含M或者rank大于等于3的文档
> db.Article.find({rank:{$in:[1,4]}}); 查询rank为1和4的文档
> db.Article.insert({title:"Mysql从删库到跑路",istop:true}); 插入文档,新增istop字段
> db.Article.find({istop:{$exists:true}}); 查询有istop字段的文档
  • MongoDB查询出指定的字段

只查询出需要的字段,不需要的字段进行舍弃。

> db.Article.find({},{field1:true,field2:1}); 查询出字段field1和字段field2的文档,1也为true的意思。
> find中有多个参数,第一个参数是检索条件,第二个参数是抽出字段。

查询测试:

> db.Article.find({},{title:true,rank:true}); 查询出字段title和字段rank的文档,其余字段不要,若有文档中
> 不包含rank字段,那么只会查询出该文档的title字段。
> 此时查询出的文档默认会把_id查出来。如果不想把_id查出来,如下:
> db.Article.find({},{title:true,rank:true,_id:0}); 这里会把id也过滤掉。
  • MongoDB文档的方法
> sort(); 文档排序
> limit(); 限制条数
> skip(); 跳过。
> 结合limit和skip实现分页

方法测试:

> db.Article.find().sort({rank:1}); rank:1是按照rank字段升序排序
> db.Article.find().sort({rank:-1}); rank:-1是按照rank字段降序排序
> 以上查询按照rank排序,会把不包含rank字段的一起查出,若不需要,过滤即可,如下:
> db.Article.find({rank:{$exists:true}}).sort({rank:1}); 过滤必须包含rank字段,然后查询排序
> db.Article.find().limit(3); 默认顺序,查询前3个文档
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).limit(3); limit只查询前3个文档
> db.Article.findOne(); 查询第一个文档
> 分页查询
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).limit(2); 首先查出前2个文档
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).skip(2).limit(2); 之后跳过前2个文档再查询2个文档
> 分页公式:(当前页 - 1) * 每页显示几条,假设每次取2条,解释:
> 第1页公式(1-1)*2=0,此时从第0条开始取,取2条。
> 第2页公式(2-1)*2=2,此时从第2条开始取,取2条。
> 第3页公式(3-1)*2=4,此时从第4条开始取,取2条。
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).skip(0).limit(2); 跳过0条,取2条
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).skip(2).limit(2); 跳过2条,取2条
> db.Article.find({rank:{$exists:true}}).sort({rank:1}).skip(4).limit(2); 跳过4条,取2条
  • MongoDB文档更新
update(<filter>,<update>,<options>)
filter:过滤器,where条件
update:更新字段的详细,比如更新哪些数据
options:更新行为,比如更新时没这条数据怎么办,比如更新时是更新一条还是多条等等

更新测试:

> db.Article.find({title:/Mysql/}); 查询标题包含Mysql的文档
> db.Article.update({title:"Mysql从删库到跑路"},{$set:{rank:7}}); 更新标题为Mysql从删库到跑路的文档,字段rank为7,之前创建该文档时没有创建rank字段,此时更新会自动加上。
> db.Article.update({title:"Mysql从删库到跑路"},{rank:7}); 和上面的区别是少了$set,意思是更新标题为Mysql从删库到跑路的文档,该文档所有字段将被清除掉,只保留一个rank为7的字段,当然其_id还是不变的,因为它还是那篇文档,该条语句更新时非常危险,不要忘记$set。
> db.Article.update({"tag":"it"},{$set:{"rank":20}}); 更新tag为it的文档字段rank为20.此时只更新默认排序中的第一个tag为it的文档,如果想更新所有tag为it的文档,需要加入options选项,如下:
> db.Article.update({"tag":"it"},{$set:{"rank":20}},{multi:true}); multi:true意思是多条文档的更新
  • MongoDB的几个特殊函数
MongoDB中所有的函数都是加$符的。
$inc:递加
$mul:相乘
$rename:改名
$set:新增or修改
$unset:字段删除

函数测试:

> db.Article.update({title:"MongoDB从入门到放弃"},{$inc:{rank:1}}); 更新标题为MongoDB从入门到放弃的文档,使其rank字段+1。
> db.Article.update({title:"MongoDB从入门到放弃"},{$mul:{rank:3}}); 更新标题为MongoDB从入门到放弃的文档,使其rank字段乘3.
> db.Article.update({title:"MongoDB从入门到放弃"},{$rename:{rank:"score"}}); 更新标题为MongoDB从入门到放弃的文档,将其rank字段更改为score字段,只对该条文档生效。
> db.Article.update({title:"MongoDB从入门到放弃"},{$set:{rank:2}}); 更新标题为MongoDB从入门到放弃的文档中的rank字段为2,该文档若原来就有rank字段则更新,若没有则新增rank字段。
> db.Article.update({title:"MongoDB从入门到放弃"},{$unset:{rank:true}}); 更新标题为MongoDB从入门到放弃的文档,将其rank字段删除,只对该条文档生效。
  • MongoDB文档的特殊更新
upsert:有则更新,无则追加。update和insert的合体
remove:条件删除数据

更新测试:

> db.Article.update({title:".net从入门到精通"},{title:".net从入门到精通",rank:35,tag:"study"},{upsert:true}); 有则更新,没有则追加
> db.Article.update({title:".net从入门到精通"},{title:".net从入门到精通",rank:100,tag:"study"},{upsert:true}); 更新rank字段
> db.Article.remove({title:".net从入门到精通"}); 删除标题为.net从入门到精通的文档
  • MongoDB使用索引
getIndexes(); 列出当前集合所有索引
createIndex({...},{...}); 创建索引
dropIndex({...)}; 删除索引

索引测试:

> db.Article.getIndexes(); MongoDB会默认为集合建一个_id的索引
> db.Article.createIndex({rank:1}); 创建一个rank字段的升序索引
> db.Article.dropIndex({rank:1}); 删除索引
> db.Article.createIndex({title:1},{unique:true}); 创建一个title升序索引,且唯一、不能重复。以后再插入数据时title就不可以重复
> db.Article.insert({title:"MongoDB从入门到放弃"}); 如果此时再插入相同title的文档,会报错,如下:
WriteResult({
        "nInserted" : 0,
        "writeError" : {
                "code" : 11000,
                "errmsg" : "E11000 duplicate key error collection: MyData.Article index: title_1 dup key: { : \"MongoDB从入门到放弃\" }"
        }
})
索引的加入要合适才好,不可乱加,否则影响性能。
  • MongoDB备份和恢复
mongodump 备份
mongorestore 恢复

使用:

> mongodump -d MyData 备份MyData数据库
> mongorestore --drop 恢复
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值