一、简介
NoSQL
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
MongoDB
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
参考:mogodb中文
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
Mongodb是时下流行的NoSql数据库,它的存储方式是文档式存储,并不是Key-Value形式。
面向文档的数据库与关系数据库有着显著的区别,面向文档的数据库用一个有组织的文件来存储数据,而不是用行来存储数据,在MongoDB中,一组文档被看作是一个集合,在关系数据库中,许多行的集合被看作是一张表。
但同时它们的操作又是类似的,关系数据库使用select,insert,update和delete操作表中的数据,面向文档的数据库使用query,insert,update和remove做意义相同的操作。
MongoDB中对象的最大尺寸被限制为4MB,但对象的数量不受限制,MongoDB可以通过集群加快操作的执行速度,当数据库变得越来越大时,可以向集群增加服务器解决性能问题。
目标:
MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统(丰富的功能)架起一座桥梁,集两者的优势于一身。根据官方网站的描述,Mongo适合用于以下场景:
◆网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
◆缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。
◆大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
◆高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对MapReduce引擎的内置支持。
◆用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询。
自然,MongoDB的使用也会有一些限制,例如它不适合以下场景:
◆高度事务性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
◆传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
◆需要SQL的问题
MongoDB支持OS X、Linux及Windows等操作系统,并提供了Python,PHP,Ruby,Java及C++语言的驱动程序,社区中也提供了对Erlang及.NET等平台的驱动程序。
二、MongoDB安装
1、下载
官网下载 有32bit和64bit,这个就要看你系统了,不过这里有两点注意:
①:根据业界规则,偶数为“稳定版”(如:1.6.X,1.8.X),奇数为“开发版”(如:1.7.X,1.9.X)。
②:32bit的mongodb最大只能存放2G的数据,64bit就没有限制。
也可以参考:菜鸟教程,下载msi格式的安装。
2、配置启动
第一步:解压到一个盘上,例如我的解压的目录C:Program FilesMongoDBServer4.0
第二步:配置存放日志和数据的目录,不然mongoDB启动不起来,如图所示:
我们在刚才的目录下,创建一个mongodb.cfg 配置文件,有两个属性logpath和dbpath,分别设定值,并且在相应盘创建对应配置路径的文件夹,如图所示:
dbpath=E:mongodbdatadb
logpath=E:mongodbdatalogmongodb.log
第三步:打开控制台cmd,进入mongodb安装目录/bin文件下运行命令:mongod.exe --config "C:Program FilesMongoDBServer4.0mongodb.cfg",来启动MongoDB服务器,--config 选项表示启动时通过mongodb.cfg,注意这里路径一定要用“”括起来,配置文件的信息配置服务器。
第四步:测试是否正常
我们在运行cmd.exe进入dos命令界面,然后进入cd C:Program FilesMongoDBServer4.0in目录下,运行mongo命令,测试一下连接,如图所示:
这时说明配置已经成功。
3、添加MongoDB到Windows Service
把MongoDB到Windows Service,用到的命令是--install
第一步:执行—install,以管理员身份启动cmd, 进入dos命令界面,先进入到cd C:Program FilesMongoDBServer4.0in目录下,执行命令:
mongod.exe --config "C:Program FilesMongoDBServer4.0mongodb.cfg" --install --serviceName "MongoDB"
安装成功就可以在服务界面去管理MongoDB了。
命令行启动/关闭MongoDB服务的方式:
net start mongodb 启动MongoDB服务
net stop mongodb 停止MongoDB服务
4、问题
安装mongodb时,最后一步,一直卡着不动
是因为到最后一步时,左下角的勾勾没有去掉,mongodb compass是图形化管理界面,下载它需要很久很久,还有可能一直下不来,所以把勾去掉就能马上安装好。
三、基础
在mongodb中基本的概念是文档、集合、数据库,
SQL术语/概念 |
MongoDB术语/概念 |
解释/说明 |
database |
database |
数据库 |
table |
collection |
数据库表/集合 |
row |
document |
数据记录行/文档 |
column |
field |
数据字段/域 |
index |
index |
索引 |
table joins |
|
表连接,MongoDB不支持 |
primary key |
primary key |
主键,MongoDB自动将_id字段设置为主键 |
通过下图实例,我们也可以更直观的了解Mongo中的一些概念:
一个mongodb中可以建立多个数据库。MongoDB的默认数据库为"db",该数据库存储在data目录中。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
"show dbs" 命令可以显示所有数据库的列表。
Show collections 显示所有表(集合)的列表
在 MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。
文档的数据结构和JSON基本一样。所有存储在集合中的数据都是BSON格式。
BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON。例如:{Name: xx,Title:yy}
四、语句
- 语句区分大小写
- 可以使用命令行或者Robo可视化工具。
在DOS环境下输入mongo命令打开shell,其实这个shell就是mongodb的客户端,同时也是一个js的编译器,自MongoDB 2.4以后的版本采用V8引擎执行所有Javascript代码,允许同时运行多个Javascript操作。所以mongo中可以执行保存好的js文件(需要执行的命令很长时 我们一般也是将命令写成js文件再执行的)。
1、插入
- 向集合(表)中插入文档(行),每次执行插入新数据
db.col.insert({title: 'MongoDB 教程', description: 'MongoDB 是一个 Nosql 数据库', by: '菜鸟教程', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 })
以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。
查看已插入文档:db.col.find()
插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
“_id": 这个字段是数据库默认给我们加的GUID,目的就是保证数据的唯一性。
- 多次执行Add 不会insert多条,可重复执行,一次插入多条数据
var templateNameObjects=[ {"templateName":"Ck _Push","MailTemplateDesc":"金航消息推送","language":"zh","subject":"預訂成功,訂單編號@(Model.OrderNo)","templateContent":"訂單編號 @(Model.OrderNo),閣下訂購已成功確認及收款,詳情已電郵給予閣下"}, {"templateName":"Tur _Push","MailTemplateDesc":"喷航消息推送","language":"zh","subject":"預訂成功,訂單編號@(Model.OrderNo)","templateContent":"訂單編號 @(Model.OrderNo),閣下訂購已成功確認及收款,詳情已電郵給予閣下"} ] templateNameObjects.forEach(function(value,index){ //添加一个 var templateName=value.templateName; var templateDesc=value.MailTemplateDesc; var templateContent=value.templateContent; var language=value.language; var subject=value.subject; var ob = db.MailTemplate.find().sort({ "MailTemplateID": -1 }).limit(1); var mailId=0; ob.forEach(function(value,index){ mailId=value.MailTemplateID+1; print(value.MailTemplateID); }); print(mailId); if(mailId>0){ //Update的第一个参数作为 匹配条件;第三个参数(upsert:true)表示不存在的话 则insert,存在的话则更新。 db.getCollection('MailTemplate').update({"MailTemplateName":templateName},{$set:{ "MailTemplateID": mailId, "MailTemplateName": templateName, "SystemCode": "Fer", "MailTemplateLanguage": language, "MailTemplateSubject": subject, "MailTemplateContent": templateContent, "MailTemplateCategoryID": 0, "Modifier": "hy", "ModifyTime": new Date(), "MailTemplateDefaultSenderAddress": null, "MailTemplateDefaultSenderDisplayName": null, "MailTemplateDesc": templateDesc }},{upsert:true}); print("添加成功!!"); }else{ print("添加失败!!"); } })
2、更新
MongoDB 使用 update() 和 save() 方法来更新集合中的文档。
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
标题(title)由原来的 "MongoDB 教程" 更新为了 "MongoDB"。
save() 方法通过传入的文档来替换已有文档。
C# 中判断是否更新成功
可以通过updateResult.ModifedCount>0 去判断
- 可重复执行(若存在则update,不存在则Add)
db.getCollection('Template').update( // query { "TemplateName": {$eq: " Electronic_Receipt"}, "SystemCode": {$eq: "Offline"} }, // update { $set: {"TemplateContent": "本人謹代表上述訂房編號之客人確認清楚明白並已核對以上之資料正確無誤"} }, // options { "multi" : false, // update only one document "upsert" : false // insert a new document, if no existing document match the query 。因为是false,所有只会更新,不会做插入 } );
3、查询
- MongoDB 与 RDBMS Where 语句比较
如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:
操作 |
格式 |
范例 |
RDBMS中的类似语句 |
等于 |
{<key>:<value>} |
db.col.find({"by":"菜鸟教程"}).pretty() |
where by ='菜鸟教程' |
小于 |
{<key>:{$lt:<value>}} |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes< 50 |
小于或等于 |
{<key>:{$lte:<value>}} |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes<= 50 |
大于 |
{<key>:{$gt:<value>}} |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes> 50 |
大于或等于 |
{<key>:{$gte:<value>}} |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes>= 50 |
不等于 |
{<key>:{$ne:<value>}} |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes!= 50 |
- find() 方法以非结构化的方式来显示所有文档。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
>db.col.find().pretty()
除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档。
- 多条件 且查询,等同and
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。
db.col.find({key1:value1, key2:value2})
- 或查询 or
db.col.find({$or: [{key1: value1}, {key2:value2}] })
- 查询大于某个时间,小于某个时间,在某一段时间范围
(>) 大于 - $gt
(<) 小于 - $lt
(>=) 大于等于 - $gte
(<= ) 小于等于 - $lte
1.Date方式
例如查询ct>=2012.12.7 且et<=2012.12.7:可翻译为 :"ct":{$gte:new Date(2012,11,7)},"et":{$lte:new Date(2012,11,7)}
如下是查询日期大于等于2016年12月1日的记录条数(注意,中间的月份写11,就是12月)
db.xxx.find({"ct":{$gte:new Date(2016,11,1)}})
2.ISODate方式
ISODate("2016-01-01T00:00:00Z")
- 查询某些字段
完整的定义:db.collection.find(query, projection)
若不指定 projection,则默认返回所有键,指定 projection 格式如下,有两种模式
db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的键,不返回其他键。。1代表包括
db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的键,返回其他键
_id 键默认返回,需要主动指定 _id:0 才会隐藏
两种模式不可混用(因为这样的话无法推断其他键是否应返回)
db.collection.find(query, {title: 1, by: 0}) // 错误
只能全1或全0,除了在inclusion模式时可以指定_id为0
db.collection.find(query, {_id:0, title: 1, by: 1}) // 正确
若不想指定查询条件参数 query 可以 用 {} 代替,但是需要指定 projection 参数:
querydb.collection.find({}, {title: 1})
querydb.collection.find({}) 也是可以的
- 限定结果条数
如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。
db.COLLECTION_NAME.find().limit(NUMBER)
还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。
db.col.find({},{"title":1,_id:0}).limit(1).skip(1) 只会显示第二条文档数据
想要读取从 10 条记录后 100 条记录,相当于 sql 中limit (10,100)。
> db.COLLECTION_NAME.find().skip(10).limit(100) 在集合中跳过前面 10 条返回 100 条数据。
skip 和 limit 结合就能实现分页。注:不要轻易使用Skip来做查询,否则数据量大了就会导致性能急剧下降,这是因为Skip是一条一条的数过来的,多了自然就慢了。
4、排序
降序:sort({MailSendTime:-1})
sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
5、索引
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
db.collection.createIndex(keys, options)
语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。
>db.col.createIndex({"title":1})
createIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。
>db.col.createIndex({"title":1,"description":-1})
6、聚合
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。
_id、num_tutorial 是结果的别名
五、Robo工具的使用
1、显示1000条,右边切换不同的显示
六、复制数据
需要使用mongodump备份与恢复
命令行中执行:
备份
Mongodump –h 127.0.0.1 –d testOne –o e:mongodbdatadump
备份本地mongo中的testOne数据库到本地目录e:mongodbdatadump下,会自动创建文件夹testOne
远程: mongodump –h xxxx:27001 –d DB –o e:mongodbdatadumpdev
还原
mongorestore -h 127.0.0.1 -d db e:mongodbdatadumpdevInfrastructureDB
七、其他参考
八、可能的问题
mongodb出现E11000 duplicate key error collection(id重复的解决办法)
具体:在mongodb中插入一条数据时,出现以下错误
E11000 duplicate key error collection: InfrastructureDB.MailTemplate index: MailTemplateID_1_MailTemplateLanguage_1 dup key: { : 1041.0, : "zh" }
一看原来是此库,含有一个组合索引MailTemplateID_1_MailTemplateLanguage_1,db中已经存在了 "MailTemplateID" : 1041且 "MailTemplateLanguage" : "zh"的数据了。所以报错。
想再插入,可以试试将索引删掉等。