MongoDB

NoSql概述
    NoSql(Not Only SQL),意即"不仅仅是SQL"
    指的是非关系型的数据库,是一项全新的数据库革命性运动



NoSql和关系型数据库的对比
    关系型数据库
        关系型数据库中的表都是存储一些结构化的数据,每条记录的字段的组成都一样,
        即使不是每条记录都需要所有的字段,但数据库会为每条数据分配所有的字段
    非关系型数据库
        非关系型数据库以键值对(key-value)存储,它的结构不固定,每一条记录可以有不一样的键,
        每条记录可以根据需要增加一些自己的键值对,这样就不会局限于固定的结构,可以减少一些时间和空间的开销.
    对应关系(仅为mongoDB和关系型数据库对比)
        关系型数据库        mongoDB
        表(table)           集合    
        记录(record)        文档(document)
        字段(field)         键(key)
        值(value)           值(value)
        主外键(PK,FK)       无
        扩展性差            扩展性强
    非关系型数据库中存储的数据没有太大的关联关系



NoSql数据库的优缺点
    优点
        简单的扩展
        快读的读写
        低廉的成本
        灵活的数据模型
    不足
        不提供对sql的支持
        支持的特性不够丰富
        现有的产品不够成熟



MongoDB基本概念
    文档(document)是MongoDB中数据的基本单元,非常类似于关系型数据库系统中的行(但是比行要复杂的多)
    集合(collection)就是一组文档,如果说MongoDB中的文档类似于关系型数据库中的行,那么集合就如同表
    MongoDB的单个计算机可以容纳多个独立的数据库,每个数据库都有自己的集合和权限
    MongoDB自带简洁但功能强大的JavaScript shell,这个工具对于管理MongoDB实例和操作数据作用非常大
    每一个文档都有一个特殊的键"_id",它在文档所处的集合中是唯一的,相当于关系型数据库中的表的主键



数据类型
    null            表示空值或未定义的对象                      {"x":null}
    布尔值          真或者假:true或false                        {"x":true}
    32位整数        shell是不支持该类型的,shell中默认会转换为64位浮点数
    64位整数        shell是不支持该类型的,shell中默认会转换为64位浮点数
    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"}}



安装
    下载: 官网http://www.mongodb.org/
    解压,并配置环境变量



启动
    服务端
        新建一个目录,用来存放数据
        启动服务,默认端口号:27017
            格式: mongod --dbpath=路径 --port 端口号
            例:   mongod --dbpath=D:\test\mongodb
    客户端
        连接服务端
            格式: mongo 地址:端口
            例:   mongo localhost:27017



常用命令
    数据库
        显示所有数据库
            show dbs
        显示当前数据库
            db
        更改当前数据库 或 创建新数据库
            use 库名    --如果数据库不存在,则自动创建
        删除当前数据库
            db.dropDatabase()
    集合
        显示当前数据库下的集合
            show collections
            show tables
        创建集合
            显示创建
                db.createCollection("集合名称")
            隐式创建(创建集合的时候,同时往集合中添加数据)
                db.集合名称.insert({name:"zhangsan",age:18})
    文档
        下面的语句都是对集合的操作,所以用法如: db.集合.find()
        查询(支持链式操作)
            查询所有
                find()
            条件查询
                find({name:"zhangsan"})
            查询指定键的值
                find({name:"zhangsan"},{age:1})
                查询name为张三的记录的age列,取决于find的第二个位置的参数,1表示只显示某列,0表示排除某列
            大于,大于等于,小于,小于等于,不等于
                find({age:($ge:99995)})
                大于,大于等于,小于,小于等于,不等于分别为:gt,gte,lt,lte,ne
            查询第一条
                findOne()
            查询个数
                count()
            排序
                sort({age:1})
                升序为1,降序为-1
            分页
                skip(2).limit(3)
                表示从2开始,查询一页,一页为3条记录
        插入
            插入一条记录
                insert({name:"zhangsan",age:18})
        删除
            删除所有
                remove({})
            条件删除
                remove({name:"zhangsan"})
        更新
            update(criteria,objNew,upsert,multi)
                criteria:用于设置查询条件的对象
                objNew:用于设置更新内容的对象
                upsert:如果记录不存在,是否要插入一条记录,0或1,默认为0
                multi:如果有多个符合条件的记录,是否全部更新,0或1,默认为0
            $set
                只修改记录中指定key的值,其它key保持不变
                例:db.aaa.update({name:"zhangsan"},{$set:{age:20}})
                如果不使用$set,则那条记录所有字段会被清空,只留一个age字段为20!!!!
            $inc
                表示使某个键值加减指定的数值
                例:db.aaa.update({name:"zhangsan"},{$inc:{age:1}})
            $unset
                用来删除某个键
                例:db.aaa.update({name:"zhangsan",{$unset:{age:1}}})
        注意:这里支持javascript语句,如插入一万条记录,可在命令行键入
            for(var i=0;i<10000;i++){
                db.集合.insert({name:"zhangsan",age:i})
            }



其它类型数据
    数组
        插入一条记录
            db.集合.insert({class:"1211",student:["zhangsan","lisi"]})
        


条件表达式
    $or
        name等于zhangsan 或 age等于18
        find($or:[{name:"zhangsan"},{age:18}])
    $nor
        name不等于zhangsan 且 age不等于18
        find($nor:[{name:"zhangsan"},{age:18}])
    $exists
        存在name键的记录,1表示存在,0表示不存在
        find({name:{$exists:1}})
    $in
        age为18或20的记录
        find({age:{$in:[18,20]}})
    $nin
        agebu为18且不为20的记录
        find({age:{$nin:[18,20]}})
    $all
        用于数组,student数组包含zhangsan和lisi的记录
        find({student:{$all:["zhangsan","lisi"]}})
    


游标
    var cc = db.集合.find();
    while(cc.hasNext()){
        cc.next();
    }



其它命令
    显示操作的执行信息
        explain()
        例: db.集合.find().explain()
    显示命令帮助,可显示指定操作后可以进行的操作
        help()
        例: db.help() , db.集合.help() , db.集合.find().help()


索引
    在数据库中,默认存在一个集合system.indexes,可显示数据库中存在的索引
    mongoDB默认为每个表的_id建立唯一索引
    为age列建立索引
        db.集合.ensureIndex({age:1})
    为age列建立唯一索引
        db.集合.ensureIndex({age:1},{unique:true})
    为age列删除索引
        db.集合.dropIndex({age:1})



固定集合
    是指事先创建好的固定大小的集合
    固定集合很像环形队列,如果空间不足,则最早的文档就会被删除
    固定集合适用于任何想要自动淘汰过期属性的场景
    命令
        db.createCollection("集合名称",{capped:true,size:1000,max:100})
        capped表示是否固定大小
        size表示文档总大小限制,单位为kb
        max表示文档总条数限制
    如果达到容量大小或条数限制,则前面的文档会被自动删除释放空间



备份和恢复,导入和导出
    使用mongoDB提供的工具mongodump/mongorestore进行备份和恢复
    使用mongoDB提供的工具mongoimport/mongoexport进行导入和导出
    在控制台进行操作,不用使用mongo连接
    备份(mongodump)
        命令
            mongodump -h 服务地址 -d 数据库名称 -o 备份文件地址
            例: mongodump -h localhost:27017 -d test -o d:\dump
    恢复(mongorestore)
        命令
            mongorestore -h 服务地址 -d 数据库名称 -o 备份文件地址
            例: mongorestore -h localhost:27017 -d test -o d:\dump
    导出(mongoexport)
        命令
            mongoexport -h 服务地址 -d 数据库名称 -c 集合名称 -o 导出目标地址 
            导出目标地址需要精确到文件名称,支持txt,word,excel等等文件
    导入(mongoimport)
        命令
            mongoimport -h 服务地址 -d 数据库名称 -c 集合名称 导入目标地址 
            这条语句后不能加分号!



安全认证(分配用户和用户登录)
    添加管理员
        use amdin
        db.addUser("root","root")
    添加普通用户
        切换到要添加用户的库
            use test
        添加读/写用户
            db.addUser("zhangsan","1234")
        添加读用户
            db.addUser("zhangsan","1234",true)
    开启安全验证
        启动服务器时
            mongod --dbpath=路径 --auth
        连接服务器进行操作前需要登录,否则报错
            db.auth("用户名","密码")



集群
    主从集群(主从复制)
        即对主服务数据的修改都会在从服务上自动同步
        从节点可以有多个
        从节点只能进行数据查询,不能进行数据修改
        启动一个主服务
            mongod --dbpath d:/master --port 10000 --master
        启动一个从服务
            mongod --dbpath d:/slaver --port 10001 --slave --source localhost:10000
        这样,则主服务上的数据改变,则自动同步到所有从服务中
    副本集
        副本集是为了避免当服务器崩溃后服务不能正常进行的情况发生
        副本集可以理解为有自动故障恢复功能的主从集群。
        主从集群和副本集最为明显的区别就是副本集没有固定的主节点
        副本集总有一个主节点(primary)和多个备份节点(secondary)
        当主节点崩溃后,副本集会从备份节点中选择一个做为主节点,继续提供服务
        只有主节点可以对数据进行读写操作,从节点不能对数据进行读和写的操作
        数据会自动从主节点同步到备份节点
        示例
            启动节点1
                mongod --dbpath d:\test\mongodb\dbs\node1 --logpath d:\test\mongodb\logs\node1\logs.txt --logappend --port 10001 --replSet setOne/localhost:10002
            启动节点2
                mongod --dbpath d:\test\mongodb\dbs\node2 --logpath d:\test\mongodb\logs\node2\logs.txt --logappend --port 10002 --replSet setOne/localhost:10001
            启动节点3
                mongod --dbpath d:\test\mongodb\dbs\node3 --logpath d:\test\mongodb\logs\node3\logs.txt --logappend --port 10003 --replSet setOne/localhost:10001,localhost:10002
            连接任意一个服务,执行初始化操作
                mongo localhost:10001
                use admin
                db.runCommand({
                    "replSetInitiate":{
                        "_id":"setOne",
                        "members":[
                            {
                                "_id":1,
                                "host":"localhost:10001",
                                "priority":3
                            },{
                                "_id":2,
                                "host":"localhost:10002",
                                "priority":2
                            },{
                                "_id":3,
                                "host":"localhost:10003",
                                "priority":1
                            }
                        ]
                    }
                })
                setOne为副本集名称,members为副本集所有节点
                priority为优先级,10001的优先级最高,则10001为主节点,10002和10003为备份节点
            查询初始化操作是否成功,连接另一个服务,执行查询
                mongo localhost:10002
                db.$cmd.findOne({ismaster:1})
                查看结果信息是否有误
            这样,如果主节点10001崩溃,则10002自动成为主节点,如果10002也崩溃,则10003自动成为主节点



分布式存储(分片)
    分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程
    将数据分散到不同的机器上,不需要功能强大的大型计算机就可以存储更多的数据,处理更多的负载
    mongoDB分片的基本思想是将集合切分成小块,这些块分散到若干个片里面
    在分片之前要运行一个路由进程(mongos),这个路由器知道所有数据的存放位置
    应用可以连接它来正常发送请求,而不需要知道数据已经被拆分了
    片键: 设置分片时,需要从集合中选一个键,用该键的值作为数据拆分的依据
    步骤:
        启动存放配置信息的服务
            mongod --dbpath D:\test\mongodb\config2222 --port 2222
        启动路由服务
            mongos --port 3333 --configdb=localhost:2222
        启动三个普通服务
            mongod --dbpath D:\test\mongodb\node4444 --port 4444
            mongod --dbpath D:\test\mongodb\node5555 --port 5555
            mongod --dbpath D:\test\mongodb\node6666 --port 6666
        连接路由服务添加配置
            mongo localhost:3333
            use admin
            db.runCommand({"addshard":"localhost:4444",allowLocal:true})
            db.runCommand({"addshard":"localhost:5555",allowLocal:true})
            db.runCommand({"addshard":"localhost:6666",allowLocal:true})
            db.runCommand({"enablesharding":"test"})
            db.runCommand({"shardcollection":"test.parson","key":{"age":1}})
            -------------------------------------------------------
            addshard添加分片,allowLocal表示是否可以直接连接普通服务
            enablesharding表示开启test数据库的分片功能
            shardcollection表示要分片的集合是parson,片键是age
        连接路由服务添加数据
            这时就可以连接路由服务添加数据了(test数据库的parson集合)
            数据会自动分布到三个普通服务上,数据量一般为均分(与片键的值有关系)



使用java操作mongoDB
    导入jar包
        mongo-java-driver-3.0.2
    测试代码
        @Test
        public void testAdd() throws UnknownHostException{
            Mongo mongo=new Mongo("127.0.0.1", 10000);
            DB db=mongo.getDB("test");
            DBCollection collection=db.getCollection("person");
            
            BasicDBObject dbObject=new BasicDBObject();
            dbObject.put("id", 1);
            dbObject.put("name", "找力宏");
            collection.insert(dbObject);
            mongo.close();
        }
        
        @Test
        public void testDelete() throws UnknownHostException{
            Mongo mongo=new Mongo("127.0.0.1", 10000);
            DB db=mongo.getDB("test");
            DBCollection collection=db.getCollection("person");
            
            DBObject dbObject=new BasicDBObject();
            dbObject.put("name", "wangxiaowang");
            collection.remove(dbObject);
            mongo.close();
        }
        
        @Test
        public void testUpdate() throws UnknownHostException{
            Mongo mongo=new Mongo("127.0.0.1", 10000);
            DB db=mongo.getDB("test");
            DBCollection collection=db.getCollection("person");
            
            BasicDBObject condtion = new BasicDBObject("_id",new ObjectId("5396bf0b0e78ffdd37b084b2"));
            BasicDBObject object = (BasicDBObject) collection.findOne(condtion);
            object.put("name", "wangwu");
            collection.update(condtion, object);
            mongo.close();
        }
        
        @Test
        public void testQuery() throws UnknownHostException{
            Mongo mongo=new Mongo("127.0.0.1", 10000);
            DB db=mongo.getDB("test");
            DBCollection collection=db.getCollection("person");
            DBCursor dbCursor=collection.find();
            
            while(dbCursor.hasNext()){
                DBObject basicDBObject=dbCursor.next();
                System.out.println(basicDBObject.toString());
                
            }
            mongo.close();
        }












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值