简介
MongoDB基于分布式文件存储的数据库。由C++语言编写。MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。所谓关系型数据库,是以行和列的形式存储数据,以便于用户理解,这一系列的行和列被称为表,一组表组成了数据库,表与表之间的数据关系通过外键维护。它支持的数据结构非常松散,是类似JSON的BSON格式,BSON和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型因此可以存储比较复杂的数据类型。
特点
1、高性能、易部署、易使用,存储数据非常方便,保留了SQL一些友好的特性(查询,索引)。
2、面向集合存储,易存储对象类型的数据
3、模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里。
4、存储在集合中的文档,被存储为键-值对的形式。键用于唯一标识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。
5、使用高效的二进制数据存储,包括大型对象(如视频等)
6、支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
7、动态查询:mongo支持丰富的查询表达方式,查询指令使用JSON形式的标记,可轻易查询文档中的内嵌的对象及数组。支持JavaScript表达式查询
8、在32位操作系统上,数据库大小限制在约2.5GB,64位系统数据库大小无限制
9、完整的索引支持:包括文档内嵌对象及数组。mongo的查询优化器会分析查询表达式,并生成一个高效的查询计划
10、支持复制和数据恢复。MongoDB 支持主从复制机制,可以实现数据备份、故障恢复、读扩展等功能。而基于副本集的复制机制提供了自动故障恢复的功能,确保了集群数据不会丢失。
使用场合
适用场合
mongodb的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统(丰富的功能)架起一座桥梁,集两者的优势于一身。mongo适用于以下场景:
a.网站数据:mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
b.缓存:由于性能很高,mongo也适合作为信息基础设施的缓存层。在系统重启之后,由mongo搭建的持久化缓存可以避免下层的数据源过载。
c.大尺寸、低价值的数据:使用传统的关系数据库存储一些数据时可能会比较贵,在此之前,很多程序员往往会选择传统的文件进行存储。
d.高伸缩性的场景:mongo非常适合由数十或者数百台服务器组成的数据库。
e.用于对象及JSON数据的存储:mongo的BSON数据格式非常适合文档格式化的存储及查询。
不适合的场景
a.高度事物性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
b.传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
c.需要SQL的问题,复杂的跨文档(表)级联查询。[
内置数据库解释
MongoDB 中多个文档组成集合,多个集合组成数据库。一个MongoDB 实例可以承载多个数据库。它们之间可以看作相互独立,每个数据库都有独立的权限控制。在磁盘上,不同的数据库存放在不同的文件中。MongoDB 中存在以下系统数据库。
● Admin 数据库:一个权限数据库,默认下没有用户是看不到的,如果创建用户的时候将该用户添加到admin 数据库中,那么该用户就自动继承了所有数据库的权限。
● Local 数据库:这个数据库永远不会被负责,可以用来存储本地单台服务器的任意集合。
● Config 数据库:当MongoDB 使用分片模式时,config 数据库在内部使用,用于保存分片的信息。
MongoDB部署与安装
1、下载mongodb的windows版本,有32位和64位版本,根据系统情况下载,下载地址:http://www.mongodb.org/downloads
2、解压缩至C:/mongodb即可
3、创建数据库文件的存放位置,比如C:/mongodb/data/db。启动mongodb服务之前需要必须创建数据库文件的存放文件夹,否则命令不会自动创建,而且不能启动成功。默认文件夹路径为c:/data/db.使用系统默认文件夹路径时,启动服务无需加--dbpath 参数说明,但文件夹还要手工创建
这里创建文件夹c:\mongodb\data\db、c:\mongodb\data\log,分别用来安装db和日志文件,在log文件夹下创建一个日志文件MongoDB.log,即c:\mongodb\data\log\MongoDB.log
4、运行cmd.exe进入dos命令界面,执行下列命令
> cd c:\mongodb\bin
> c:\mongodb\bin>mongod -dbpath "c:\mongodb\data\db"
Waiting for connections on port 27017 看到类型信息说明启动成功,默认MongoDB监听的端口是27017
5、测试连接
新开一个cmd窗口,进入mongodb的bin目录,输入mongo或者mongo.exe,显示当前数据库版本,出现connecting to:test默认进入test数据库,说明测试通过。
输入exit或者ctrl+C可退出。
注册服务
当mongod.exe被关闭时,mongo.exe就无法连接到数据库了,因此每次想使用mongodb数据库都要开启mongod.exe程序,所以比较麻烦,此时我们可以将MongoDB安装为windows服务
1、 确保配置MongoDB存放数据的文件夹db中的内容为空(每次配置数据路径或注册服务都会在该文件夹内产生一些配置文件),清除该文件夹中的内容
2、 以管理员身份运行cmd,执行下列命令
跳转到bin目录,执行mongod--logpath C:\MongoDB\data\log\MongoDB.log --logappend --dbpathC:\MongoDB\data\db -auth --directoryperdb --serviceName MongoDB -install
其中logpath与dbpath后面是对应用户自定义的日志写入文件目录和数据保存目录,--serviceName "MongoDB" 意思是服务名为MongoDB,--logappend意思是日志记录方式为追加方式,-auth意思是开启权限验证,如果不需要权限验证可以不加
3、接着启动mongodb服务
> c:\mongodb\bin>NET START MongoDB
打开任务管理器,可以看到进程已经启动
注:>c:\mongodb\bin>NET stop MongoDB (关闭服务)
C:\Windows\system32>sc deleteMongoDB (删除服务)
用户权限管理
首先需要确定当前数据库版本,在每次启动访问时会显示出来,也可以用db.version()命令在数据库里边查看,目前最新版本是3.0.4,所以这里的一切说明都是在该版本下操作演示的。
1、 首先确认数据库没有开启权限验证,如果已经注册了服务且开启了权限验证,可以修改注册表HKEY_LOCAL_MACHINE->SYSTEM->ControlSet001->services->MongoDB,修改ImagePath所对应值,在dbpath c:\mongodb\data\db -auth中把"-auth"去掉,之后重启服务就可以了
2、 打开新cmd窗口跳转MongoDB的bin目录下,输入mongo进入数据库。
3、 输入命令:show dbs,会显示一个数据库: local,在老版本中所谓的admin是不存在的。Mongodb中没有超级权限,只有可以管理用户的权限userAdminAnyDatabase
4、 添加管理用户:
use admin
db.createUser(
{
user: "root",
pwd: "root",
roles: [ { role: "userAdminAnyDatabase",db: "admin" } ]
}
)
这是在创建admin库后,添加一条user记录,user对应为用户名,pwd对应为密码,roles对应为权限,里边role是具体的权限,userAdminAnyDatabase是管理用户的权限,db所对应是该权限所应用的数据库。
5、切换到admin下,查看刚才创建的用户:
show users
可以看到刚才创建的用户的信息
7、数据库默认是没有开启权限认证的,下面进行手动开启
重新启动mongodb:进入bin目录,mongod-dbpath "c:\mongodb\data\db" –auth,之后打开新窗口开启mongodb。若是注册过了服务可以继续修改注册表
8、用刚才建立的用户登录
use admin
db.auth("root"," root ") #认证,返回1表示成功
因为用户root只有用户管理的权限,所以再创建一个用户,分配其读写权限
use collectInfo (建立collectInfo中的用户)
db.createUser(
{
user: "test",
pwd: "test",
roles: [
{ role: "readWrite", db: "info"}
]
}
)
这里又创建了一个test用户,权限是info库的读写操作
9、查看刚刚创建的用户
show users
查看整个mongoDB全部的用户
use admin
db.system.users.find()
10、进入相应数据库后,进行登录,可以看到该库数据
use collectInfo
db.auth(“test”,”test”)
show collections
用Java操作MongoDB
首先,下载mongoDB对Java支持的驱动包,并在Java工程中导入,启动mongod.exe的服务
Mongo m = newMongo("localhost",27017);
这样就创建了一个MongoDB的数据库连接对象,它默认连接到当前机器的localhost地址,端口是27017。
DB db = mongo.getDB(“test”);
这样就获得了一个test的数据库,如果mongoDB中没有创建这个数据库也是可以正常运行的。如果你读过上一篇文章就知道,mongoDB可以在没有创建这个数据库的情况下,完成数据的添加操作。当添加的时候,没有这个库,mongoDB会自动创建当前数据库。
DBCollection t = db.getCollection("t");
这样就获得了一个DBCollection,它相当于我们数据库的“表”。
查询所有数据
DBCursor cur = t.find();
while (cur.hasNext()) {
System.out.println(cur.next());
}
查看该库所有集合
Set<String> colls =db.getCollectionNames();
for (String s : colls) {
System.out.println(s);
}
插入数据
mongodb存储JSON格式的文档,而在Java中表示这种数据格式的最简便的类就是Map了。MongoDB Java Driver中提供的BasicDBObject就是个Map(它继承自LinkedHashMap并实现DBObject接口),它会将Map中的数据转换成BSON格式传输到mongodb。下面是插入文档的示例:
DBCollectioncoll = db.getCollection("t");
BasicDBObjectdoc = new BasicDBObject();
doc.put("name","kafka0102");
doc.put("age",28);
doc.put("time",new Date());
coll.insert(doc);
mongodb中每个插入的文档会产生个唯一标识_id。当调用coll.insert(doc);时,driver会检查其中是否有_id字段,如果没有则自动生成ObjectId实例来作为_id的值,这个ObjectId由4部分编码而成:当前时间、机器标识、进程号和自增的整数。
insert函数也支持插入文档列表:
List<DBObject> list = newArrayList<DBObject>();
DBObject user = new BasicDBObject();
user.put("age", 22);
list.add(user);
DBObject user2 = newBasicDBObject("name", "lucy");
list.add(user2);
coll.insert(list)
而提交操作也有update( DBObject q , DBObject o )、remove( DBObject o )。
条件删除
t.remove(new BasicDBObject("age",new BasicDBObject("$gte", 24))) 删除age字段大于等于24的数据
使用Java登录数据库
使用Java验证用户登录时,注意3.0以后版本mongodb加入了SCRAM-SHA-1校验方式,需要第三方工具配合进行验证,下面给出具体解决办法:
首先关闭认证,修改system.version文档里面的authSchema版本为3,初始安装时候应该是5,命令行如下:
> use admin
switched to db admin
>var schema = db.system.version.findOne({"_id" :"authSchema"})
>schema.currentVersion = 3
3
> db.system.version.save(schema)
WriteResult({ "nMatched" : 1, "nUpserted" : 0,"nModified" : 1 })
之后再建立的用户验证方式就是MONGODB-CR这种啦,注意是修改后再建立的用户才行,DB.authenticate(username,password.toCharArray())方法验证通过
使用索引
创建索引语句如:coll.createIndex(new BasicDBObject(“i”, 1)); ,其中i表示要索引的字段,1表示升序(-1表示降序)。可以看到,DBObject成为java客户端通用的结构表示。查看索引使用DBCollection.getIndexInfo()函数
Mongodb复杂命令
db 查看当前数据库
db.removeUser() 删除用户
db.createCollection('hello') 创建集合,直接insert或save数据也能创建集合
db.hello.renameCollection('hehe') 重命名集合
db.dropDatabase() 删除数据库
db.user.find({salary:{$gt:5000}}) 查询salary大于5000的数据
db.user.find({name:/a/}) 查询name中包含'a'的数据
db.user.find({name:/^G/}) 查询name以G打头的数据
db.user.find({age:{$lt:30},salary:{$gt:6000}})
查询age小于30,salary大于6000的数据
db.user.find({$or:[{salary:{$gt:10000}},{age:{$lt:25}}]})
查询age小于25,或者salary大于10000的记录
db.user.find({},{name:1,age:1,salary:1})
查询user集合中所有记录的name,age,salary字段,这里的1表示显示此列的意思,也可以用true表示
db.user.find().limit(3) 显示结果集中的前3条记录
db.user.find().skip(1) 查询第1条以后的所有数据
db.user.find().sort({salary:1}) 对结果集升序排序,降序为-1
db.user.find().count() 统计集合中的所有记录条数
db.user.find({$or: [{salary: {$lt:4000}},{salary: {$gt:10000}}]}).count()
查询salary小于4000或大于10000的记录数
save与insert功能基本一样,不同在于对于有主键的数据save会执行修改,insert会报错
db.t.update({name:'n1'},{sex:1})
将查询到的数据所有字段改为sex:1
db.t.update({name:'n1'},{$inc:{age:5}})
$inc修改器:将指定属性的值增加特定的步长,如果键不存在则创建它
$set修改器:用来指定一个键的值,如果不存在则创建它
db.t.update({name:'n2'},{$inc:{age:5}},true)
将update的第3个参数设为true就是upsert操作了,如果有符合更新条件的文档,则正常更新,没有则创建修改内容(其实是插入一条name为n2的数据,再修改为age:5)。如果没有name为n2的数据,会创建一条age为5的数据
批量更新只需将update的第4个参数设为true即可。
db.t.ensureIndex({ID:1})
建立索引在t集合上,建立对ID字段的索引,1代表升序。
数据库还原与备份
备份数据库
mongodump -h IP--port 端口 -u 用户名 -p 密码 -d 数据库 -o 文件存在路径
还原数据库
mongorestore -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 --drop 文件存在路径
|
如果没有用户,可以去掉-u和-p。
如果导出本机的数据库,可以去掉-h。
如果是默认端口,可以去掉--port。
如果想导出所有数据库,可以去掉-d。
--drop的意思是先删除存在的库再导入新库
数据表操作
数据表导出:mongoexport -h IP --port
端口 -u 用户名 -p 密码 -d 数据库 -c 表名 -f 字段 -q 条件导出 --csv -o 文件名
-f 导出值字段,以字号分割,-fname,email,age导出name,email,age这三个字段
-q可以根查询条件导出,-q '{ "uid" : "100" }' 导出uid为100的数据
--csv 表示导出的文件格式为csv的,这个比较有用,因为大部分的关系型数据库都是支持csv,在这里有共同点
还原整表导出的非csv文件:mongoimport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 --upsert--drop 文件名
还原导出的csv文件:mongoimport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 --type 类型--headerline --upsert --drop 文件名