MongoDB私人学习笔记

ops/2025/2/27 1:32:59/

俗话说“好记性不如烂笔头”,编程的海洋如此的浩大,养成做笔记的习惯是成功的一步!

笔记主要是ZooKeeper3.4.9版本的笔记,并且笔记都是博主自己一字一字编写和记录,有错误的地方欢迎大家指正。


    一、基础知识:
    
        1、MongoDB的名称来源于Humongous Database,中文意思就是巨大无比的数据库,顾名思义,MongoDB就是为处理大数据而生, 以解决海量数据的存储和高效查询使用为使命。是NoSQL数据库的一种,是基于文档保存数据的形式,有C++语言编写的开源数据库系统。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成,MongoDB 文档类似于 JSON 对象,有数值、字符串、布尔值、日期、数组、对象ID等类型,字段值还可以包含其他文档,数组及文档数组。
          官方网址:https://www.mongodb.com
        
        
        2、MongoDB通常在如下情形下考虑使用:
            1)用作操作日志的记录,例如用户在网站上的操作行为记录。
            2)记录的数据是比较松散,没有统一结构的形式的数据。因为MongoDB本身存储的数据是不需要有强硬的结构化。
            3)大尺寸、低价值的数据,例如日志信息、大量的消息推送记录等数据。
            4)高伸缩性的场景,因为MongoDB性能高,并且非常容易扩展,有着强大的集群功能。
        
            注意:MongoDB本身不支持事务和多表(文档)的级联,故如果有此需求的场景,不应该使用MongoDB。
        
        
        
        3、mongodb3.2.11-linux-x86_64-rhel70-3.2.11.tgz是基于Linux readHead系统的安装文件(CentOS系统也适合使用)。mongodb-linux-x86_64-2.4.9.tgz是旧版本的安装文件,留着备用。
           注意:此笔记都是基于3.2.11版本来记录的。
           
           mongodb.conf是基本的配置文件,本身压缩包是没有创建配置文件的,需要自己去创建。
        
           jar_lib文件夹存放的是java连接MongoDB的jar包。jar包下载地址http://central.maven.org/maven2/org/mongodb/mongo-java-driver/
           
           
        
        
        4、Mongodb与传统的关系型数据的术语对应关系:
              RDBMS(关系型数据库管理系统)                   MongoDB
                数据库                                    数据库
                表格                                    集合
                行                                        文档
                列                                        字段
                表联合                                    嵌入文档
                主键                                    主键 (MongoDB 提供了 key 为 _id)
        
        
        
        
        5、MongoDB默认的服务端口是27017,默认的数据库文档存储路径为 /data/db,默认情况下只允许本地通过127.0.0.1地址来访问,
           如果允许通过其他ip地址来访问,则需要配置bind_ip=0.0.0.0,开放通过所有地址均可访问。
        
        
        6、MongoDB的特性:
            (1)对于单个文档,MongoDB的操作是原子性的,即操作单个文档是数据安全的。
            
            (2)本身不支持事务,但是可以通过组合一些命令来达到简单的事务效果,但是无法实现复杂的事务情形。
               可以参考官方网站的例子,通过两阶段提交来实现简单的事务效果。
               地址:https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits
               
            (3)MongoDB默认的数据库标识是自动生成的,字段名称为_id,值为ObjectId类型,并且ObjectId内部的值是唯一的。
               如果在存储数据时指定了_id字段,那么将不再自定生成。存储的格式例子:
                { "_id" : ObjectId("583c6a7a9abb612322fd08c8"), "2" : true, "a" : 1 }
                { "_id" : ObjectId("583c6be49abb612322fd08c9"), "2" : true, "a" : 1 }
                { "_id" : 123, "a" : 1 }
                
                如果手动设置ObjectId类型,长度必须要求为24位。  
                
            
            (4)MongoDB的shell脚本操作使用的是JavaScript脚本语言,故拥有JavaScript语言的特性,例如区分大小写,单双引号的使用,
               浮点型数值精度丢失,定制JSON对象等。
        
        
        
        7、MongoDB的集群:
            1、replica set 通过副本集的方式来达到集群的效果,但是仅仅没有负载均衡的能力。由一个主节点多个从节点的形式组成,默认所以的读写操作都在主节点上(可以设置从节点拥有读的能力,但不可以设置写操作),数据会自动同步
                           到从节点。当主节点宕机后,会自动选取从节点升级为主节点,接替主节点的工作,故拥有容灾备份的能力,
                           但是因为同一时刻只有一个主节点,所以没有负载均衡的能力。
            
            
            2、sharding 通过分片区的方式来达到负载均衡的效果,但是没有容灾备份的能力。将数据进行分片,由多个服务器来分别承担分片数据,通过路由计算规则来觉得存储的数据所在的分区位置,故客户端对数据的读写操作,可能分到不同的片区由不同的服务器来处理,达到了负载均衡的能力,但是如果有个别片区的服务宕机了,那么就无法提供这一片区的数据服务,没有容灾备份的能力。
                        
                        
                        
            3、sharding + replica set 集合分片区和副本集的特性,将其整合在一起,使得既有容灾备份的效果,又有负载均衡的能力。相当于将sharding分片区进行分组,每个分片区组都存储完整的数据,一个组就相当于一个副本集,建立多个组就相当于有多个副本集,当一个组的sharding分片区有服务器宕机时,其他组的sharding分片区服务器能马上代替其工作。
                                      
                                      
            附加:主从节点的数据复制是根据oplog(operation log)操作日志来同步的,从节点读取主节点的oplog来更新自己的数据库。oplog达到指定大小时,会滚动到文件头重新记录,覆盖掉以前的操作日志,故oplog的空间不能过于小,导致从节点同步数据丢失。
                    
        


        8、mongodb自带有命令形式的客户端,可以通过mongo命令登录进行操作mongodb。如果需要图形界面来操作,则需要额外安装图形界面的应用来支持,或者使用图形工具软件来连接。常用的有如下几款:
            MongoDBCompass(官方版):地址为 https://www.mongodb.com/try/download/compass?jmp=docs
            Robo 3T(原名:Robomongo)
            mongobooster
        
            
            
        
    
    二、使用笔记
        1、最简单的形式启动服务:
            解压mongodb3.2.11-linux-x86_64-rhel70-3.2.11.tgz后,进入解压后的bin目录,执行如下命令便可以简单的启动MongoDB服务:
             ./mongod --dbpath=/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/data/db 
            
             注意:--dbpath是指定数据库路径,必须要先创建好该路径目录。
                 MongoDB的数据库文档默认是存储在/data/db目录下的,如果没有预先创建好该目录会启动报错。
                 注意是mongod命令,不是mongo命令,bin目录下有两个名字非常相近的命令,但功能是完全不同的。
                 
            
            附加:MongoDB关闭服务的方式:
                (1)执行mongod命令来关闭 ./mongod --shutdown --dbpath=/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/data/db 
                   必须要指定好正确的db路径,因为停止服务时要移除数据库的锁标识。
                   
                 
                (2)进入mongo的shell操作工具(执行命令./mongo 127.0.0.1:27021来进入操作工作),切换到admin数据库来停止服务。
                    use admin
                    db.shutdownServer()
                    
                    
                (3)查询进程进行kill掉。
                    ps -ef|grep mongo
                    kill 进程号
            
                 
        2、进入bin目录,可以通过 ./mongod -h 来查看更多的可执行参数,"mongod命令可以使用的参数列表.txt"就是可以执行的参数列表。
        
        
        
        
        3、通过指定配置文件来启动服务:
            进入解压的目录,执行命令:     ./bin/mongod --config mongodb.conf
            
            其中mongodb.conf是自己创建的配置文件(注意文件路径),其中最基本的配置内容有:
            
                #数据库路径
                dbpath=/usr/local/mongodb/db
                #日志路径
                logpath=/usr/local/mongodb/logs/mongodb.log
                #以追加方式写入日志
                logappend=true
                #默认的服务端口
                port=27017
                #后台形式运行服务,使用此形式必须要配置日志路径
                fork=true
                #禁用http查看界面。默认就是关闭的。
                nohttpinterface=true
        
        
        4、MongoDB的http查看界面,是通过web形式展现的,默认是没开启此功能的,需要配置 nohttpinterface=false 
           如果想让web界面提供更多的功能,需要在启动时指定 -rest参数,如:  ./bin/mongod --config mongodb.conf -rest
           
           本地启动该服务后,可以在web查看到所有的命令 http://localhost:28017/_commands
        
        
        
        5、常用命令:
            (1)普通命令:
                show dbs                     查看所有的数据库
                use mydb                     使用mydb数据库
                show collections             查看当前数据库下的所有集合(表)
                db                             当前数据库引用,对数据库的操作都需要db开头
                db.stats()                     查看当前数据库的状态
                db.version()                使用的MongoDB版本号。
                db.getMongo()                查看当前连接数据库的地址。
                db.mydb.isCapped()            查看当前集合是否固定长度的集合。
                db.createCollection("mydb") 创建集合,默认创建的是非固定长度的集合。
                db.createCollection("mydb",{capped:true,size:10000,max:1000}) 创建固定长度的集合,size表示集合大小,max表示文档数。
                db.runCommand({"convertToCapped":"mydb",size:10000})      将已存在的mydb集合转换为固定长度的集合。
                
                
                
            (2)删除命令    
                db.dropDatabase()            删除当前数据库。
                
                db.col_name.drop()            删除集合。col_name是集合名词。
                
                
                db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <number>})
                    query :(可选)删除的文档的条件。
                    justOne : (可选)如果设为 true 或 1,则只删除一个文档。默认为false,即删除所有符合条件的文档。
                    writeConcern :(可选)抛出异常的级别。有-1,0,1,2级别,默认级别是1,即如果写入失败则立刻返回错误。
                    
                    例子:
                        删除mycoll集合下的所有数据。
                        db.mycoll.remove({})
                        
                        删除标题为mongo的所有数据。
                        db.mycoll.remove({"title":"mongo"})
                        
                        删除标题为mongo的第一条数据。
                        db.mycoll.remove({"title":"mongo"},true)
                        
                
            
            
            (3)新增命令
                db.mycoll.insert({'key01':'val01','key02':'val02'})        
                    插入数据到mycoll集合中,如果该集合不存在,则会新建一个。
                    
                db.mycoll.save({'_id':ObjectId("56064f89ade2f21f36b03136"),'key01':'val01','key02':'val02'})        
                    保存数据。如果有_id=56064f89ade2f21f36b03136的数据,即数据已经存在,则直接进行替换,否则就插入新的数据。
            
            
            
            
            (4)更新命令
                db.collection.update(<query>,<update>,{upsert: <boolean>,multi: <boolean>,writeConcern: <number>})
                    query : update的查询条件,类似sql update查询内where后面的。如果需要更新所有数据,则直接传入{}空json对象。
                    update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
                    upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
                    multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
                    writeConcern :可选,抛出异常的级别。
                    
                    例子:
                        替换title为mongo的第一条数据,注意是替换形式,既把title为mongo的记录直接就变为title:"newMongoDB",states:"ok"。
                        db.mycoll.update({title:"mongo"},{title:"newMongoDB",states:"ok"},false)
                        
                        更新title为mongo的第一条数据,使用了$set操作符,注意不是替换,是局部更新。
                        db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}})
                        
                        更新title为mongo的所有数据。ps:如果该数据没有states字段,那么就好新增此字段,如果有就直接更新。
                        db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}},false,true)
                        
                        更新title为mongo的的数据,如果不存在任何的记录,则插入更新的数据。
                        db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}},true,false)
                        
                        更新所有的数据,所有money字段的值+1,如果money字段不存在,则新增money字段,值设置为1。
                        db.col.update({},{$inc:{"money":1}},{multi:true})
                    
                    注意:在更新数据时,对于已经存在的字段则进行更新操作,如果该数据没有更新的字段,则会新增此字段。
                    
                        
                
            
            (5)查询命令
                db.mycoll.find()                查询mycoll集合的所有文档。
                
                db.mycoll.findOne()                查询当前mycoll集合的文档,只获取第一条数据,并美化后才输出。
                
                db.mycoll.find().pretty()        查询mycoll集合的所有文档,并美化后才输出。
                
                db.mycoll.find().limit(<num>)    限制条数查询。num是限制的条数,如果没输入任何数值,则默认查询全部。
                
                db.mycoll.find().skip(<num>)    对查询结果跳过指定的条数。num是限制的条数,如果没输入任何数值,则默认不跳过任何条数。
                                                ps:附加命令pretty、limit等命令,是可以组合在一起使用的。
                
                db.col.find().sort({<key>:-1})  查询结果进行排序。key是排序字段,值-1表示降序,1表升序。可以使用多个字段按顺序排序。
                                                ps:如果数据没有该排序字段,则认为是属于最小值,降序中排在最后。
                
                
                find()和findOne()都可以带条件查询,查询的条件:
                    AND条件: db.mycoll.find({title:"mongo",state:"ok"})                        查询title="mongo" AND state="ok"的数据。
                    OR条件: db.mycoll.find({$or:[{title:"mongo"},{state:"ok"}]})             查询title="mongo" OR state="ok"的数据。
                    IN关键字:db.mycoll.find({_id:{$in:[1,2,3,4]}})                         查询_id为1,2,3,4中任何一个数值的数据。
                    等于:    {<key>:<value>}    db.col.find({"by":"菜鸟教程"})                    相当于where by = '菜鸟教程'
                    等于写法2:    {<key>:{$eq:<value>}}    db.col.find({"by":{$eq:"mon"}})     相当于where by = 'mon'
                    小于:    {<key>:{$lt:<value>}}    db.col.find({"likes":{$lt:50}})            相当于where likes < 50
                    小于或等于:    {<key>:{$lte:<value>}}    db.col.find({"likes":{$lte:50}})    相当于where likes <= 50
                    大于:    {<key>:{$gt:<value>}}    db.col.find({"likes":{$gt:50}})            相当于where likes > 50
                    大于或等于:    {<key>:{$gte:<value>}}    db.col.find({"likes":{$gte:50}})    相当于where likes >= 50
                    不等于:    {<key>:{$ne:<value>}}    db.col.find({"likes":{$ne:50}})            相当于where likes != 50
                    类型查询:{<key>:{$type:<value>}}  db.col.find({"likes":{$type:2}})     查询likes字段值类型是String字符串类型的,类型详见附加。
                    正则表达式:{<key>:{$type:/<value>/}} db.col.find({"name":/^china/i})    查询name名称已china开头并且不区分大小写的数据。
                    正则表达式写法2: db.col.find({"name":{$regex:"^china",$options:"$i"}})    查询name名称已china开头并且不区分大小写的数据。
                    
                    其他例子:
                        查询 title="mongo" AND (state="OK" OR date=ISODate("2016-11-29T02:48:10.115Z"))的数据
                        db.mycoll.find({title:"mongo",$or:[{state:"ok"},{date:ISODate("2016-11-29T02:48:10.115Z")}]})
                        
                        查询 (title="mongo" AND state="OK") OR (date=ISODate("2016-11-29T02:48:10.115Z"))的数据
                        db.mycoll.find({$or:[{title:"mongo",state:"ok"},{date:ISODate("2016-11-29T02:48:10.115Z")}]})
                
                
                find()和findOne()可以指定输出的字段:
                    查询标题为mongo的数据,并且只显示title和falg字段值,其中_id是默认显示的。
                    db.mycoll.find({"title":"mongo"},{title:1,flag:1})    
                    
                    查询第一条数据,并且只显示title和falg字段值,_id不显示。
                    db.mycoll.findOne({},{_id:0,title:1,flag:1})  
                
                
                    
                    
            
            
            (6)索引命令
                db.collection.ensureIndex({<key>:-1}}, <option>)    给集合创建索引。当数据量大时,必须创建索引才能加快查询速度,注意默认_id没有加入索引的。
                
                例子:
                        给mycol的title字段创建升序索引,给description字段创建降序索引,相当于传统数据库的联合索引,注意字段顺序。
                    db.mycoll.ensureIndex({"title":1,"description":-1})
                    
                        给mycol的title字段创建升序索引,并且通过后台运行的方式来创建。ps:创建索引时会阻塞其他数据库操作,可通过后台方式来防止此情况。
                    db.mycoll.ensureIndex({open: 1}, {background: true})
                    
                        给mycol的title字段创建升序索引,后台方式运行,并且要求title是唯一索引。dropDups表示相同的title记录是否删除,默认不删除。
                    db.mycoll.ensureIndex({title: 1}, {background: true,unique:true,dropDups:false})
            
                
                提示:如果查询的数据字段都是同一个索引的一部分,那么直接是从索引中获取查询结果,而无需再查找文档,速度将非常的快。
                      例如:创建索引db.users.ensureIndex({gender:1,user_name:1})  ,然后查询db.users.find({gender:"M"},{user_name:1,_id:0})。
                    
                注意:集合中索引不能超过64个,索引名的长度不能超过125个字符,一个复合索引最多可以有31个字段。可以通过explain()来查看查询是否使用了索引。
            
            
            (7)聚合命令
                db.collection.aggregate(<option>)  聚合操作主要用于处理数据(例如统计、计算平均值等),并返回处理结果。
            
                例子:
                        根据money字段进行分组,并统计出各分组的总金额。ps:$group操作符,_id字段是必须要写的,表示分组字段。
                    db.mycol.aggregate({$group:{_id:"$money",total:{$sum:"$money"}}})
            
                    
                        先用match进行数据过滤,要求金额必须大于21小于等于60,然后对其数据进行分组,统计出总数量。
                        注意_id:null表示所以数据合并为一个分组。此处使用了MongoDB的概念,对match操作后的数据给group进一步操作。
                    db.col.aggregate([{$match:{money:{$gt:21,$lte:60}}},{$group:{_id:null,count:{$sum:1}}}])
                        
                        对文档数据输出进行定制。$project操作符就是修改输出的数据。只输出_id,money,flag字段的数据,
                        其余字段一律不输出,并且flag的数据来源于state字段,相当于给输出字段修改名称。
                    db.col.aggregate({$project:{_id:1,money:1,flag:"$state"}})
            
            
        6、特殊的命令详解:
            (1)insert和save的区别:
                insert 是直接插入数据,如果主键已经存在,则会报_id_ dup key主键重复的异常,导致插入失败。
                
                save  也是插入数据,但是如果主键已经存在,则是直接进行更新。
                
            
            (2)save和update的区别:
                save      如果数据存在,则是直接进行替换,而非局部更新。
                
                update  如果没有指定$set操作符,则和svae功能一样,是属于直接替换。
                        如果使用了$set操作符,则只对指定的字段进行更新,属于局部更新,并且可以同时更新多条数据。
                
                
                
                
        7、MongoDB的备份与恢复:
            (1)备份操作:
                mongodump -h dbhost -d dbname -o dbdirectory
                    -h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
                    -d:需要备份的数据库实例,例如:test
                    -o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,
                        系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
                        
            
            (2)恢复操作:
                mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
                    -h:MongoDB所在服务器地址
                    -d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
                    --directoryperdb:备份数据所在位置,例如:c:\data\dump\test。
                    --drop:恢复的时候,先删除当前数据,然后恢复备份的数据。慎用!
                
        
        
        8、MongoDB自带的监控工具:
            (1)状态监测工具:
                mongostat
                
                
            (2)操作耗时监测工具:
                mongotop <num> 
                    <num> 是监测间隔,表示多少秒一次获取监测数据,默认1秒。
                
    
        
        
        9、默认情况下,mongodb是不需要验证的,如果要开启验证,则需要在配置文件中设置并且创建账号密码,步骤如下:
            (1)进入其中一个数据库(通常是使用默认的admin库):use admin
            
            (2)创建用户:
                         db.createUser({user:"admin",pwd:"tcljr@*2020",roles:["root"]})
                         db.createUser({user:"tcljr",pwd:"tcljr@*2020",roles:["readWrite"]})
                         db.createUser({user:"riskmg",pwd:"tcljr@*2020",roles:[{role:"readWrite",db:"sit-riskmg"}]})
                
                        说明:如果没有指定db,则默认是使用当前数据库名的集合。如果需要给不同数据库创建用户,需要切换到不同数据库后再创建。
                
                
                
            (3)在配置文件中,将auth=true,然后重启mongodb服务。
            
            
            
            (4)通过moongodb的shell客户端进入 ./bin/mongo 10.0.112.35:27017
            
            
            (5)切换到对应数据库,然后进行验证:
                use admin
                db.auth("admin","tcljr@*2020")
                
                注意:必须要先选择数据库,如果选择的数据库不正确,即使账号密码正确都会认证失败。
                说明:如果不进行验证,则是无法查看数据库和数据的,例如show dbs会不显示任何数据库。
                
                
            
            (6)如果是有使用副本集群,如果开启了auth=true认证,则必须要配置认证文件keyFile,否则集群节点之间无法通讯。
                keyFile文件可通过 openssl rand -base64 1024 > mongodb.key   来生成,生成的字符长度如果超过1024,则可以手动删除一部分。
            

    
    
    
    
    三、java使用MongoDB的方式:
        1、http://central.maven.org/maven2/org/mongodb/mongo-java-driver/
    
    
    
        2、SpringBoot整合mongodb
            (1)增加maven依赖:
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-mongodb</artifactId>
                </dependency>
            
            
            (2)配置application.yml文件: 
                spring: 
                  data:
                    #mongodb配置(集群配置(也可以用于单机))
                    mongodb:
                      uri: mongodb://10.0.112.35:27017,10.0.112.35:27018,10.0.112.36:27017,10.0.112.36:27018,10.0.112.37:27017/riskmg
   
                    #mongodb配置(单机配置)
                    
                    
    
            (3)直接注入MongoTemplate依赖即可使用:
                    @Resource
                    private MongoTemplate mongoTemplate;
    
    
    
    
    
                
/*************************************************************附加*******************************************************/
        1、MongoDB 中可以使用的类型如下表所示:
            类型                            数字    
            Double                              1     
            String                             2     
            Object                             3     
            Array                             4     
            Binary data                         5     
            Undefined                         6      已废弃。
            Object id                         7     
            Boolean                             8     
            Date                             9     
            Null                             10     
            Regular Expression                 11     
            JavaScript                         13     
            Symbol                             14     
            JavaScript (with scope)             15     
            32-bit integer                     16     
            Timestamp                         17     
            64-bit integer                     18     
            Min key                             255     Query with -1.
            Max key                             127                     
        
        
        

    2、原子操作常用命令
        $set
            用来指定一个键并更新键值,若键不存在并创建。
            { $set : { field : value } }
            
        $unset
            用来删除一个键。
            { $unset : { field : 1} }
            
        $inc
            $inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
            { $inc : { field : value } }
            
        $push
            用法:
            { $push : { field : value } }
            把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去。
            
        $pushAll
            同$push,只是一次可以追加多个值到一个数组字段内。
            { $pushAll : { field : value_array } }
            
        $pull
            从数组field内删除一个等于value值。
            { $pull : { field : _value } }
            
        $addToSet
            增加一个值到数组内,而且只有当这个值不在数组内才增加。
        
        $pop
            删除数组的第一个或最后一个元素
            { $pop : { field : 1 } }
        
        $rename
            修改字段名称
            { $rename : { old_field_name : new_field_name } }
        
        $bit
            位操作,integer类型
            {$bit : { field : {and : 5}}}
        
        
        


    3、原子操作数据模型
        考虑下面的例子,图书馆的书籍及结账信息。
        实例说明了在一个相同的文档中如何确保嵌入字段关联原子操作(update:更新)的字段是同步的。
        book = {
                  _id: 123456789,
                  title: "MongoDB: The Definitive Guide",
                  author: [ "Kristina Chodorow", "Mike Dirolf" ],
                  published_date: ISODate("2010-09-24"),
                  pages: 216,
                  language: "English",
                  publisher_id: "oreilly",
                  available: 3,
                  checkout: [ { by: "joe", date: ISODate("2012-10-15") } ]
                }
        你可以使用 db.collection.findAndModify() 方法来判断书籍是否可结算并更新新的结算信息。
        在同一个文档中嵌入的 available 和 checkout 字段来确保这些字段是同步更新的:
        db.books.findAndModify ( {
           query: {
                    _id: 123456789,
                    available: { $gt: 0 }
                  },
           update: {
                     $inc: { available: -1 },
                     $push: { checkout: { by: "abc", date: new Date() } }
                   }
        } )
        
        
        
    4、ObjectId类型
        (1)ObjectId 是一个12字节 BSON 类型数据,有以下格式:
            前4个字节表示时间戳
            接下来的3个字节是机器标识码
            紧接的两个字节由进程id组成(PID)
            最后三个字节是随机数。
            
            
        (2)    手动创建ObjectId对象:myobj = new ObjectId()  或者myobj = ObjectId()
        
        (3)ObjectId的可操作api:
            ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()  获取对象时间戳。
            new ObjectId().str    获取对象标识的字符串格式。
            
            
            
    5、实现_id的自增长
        MongoDB的主键id不支持数值自增长的形式,可以通过编写自定义函数来实现。
        
        //自定义增长的函数
        function getNextSequenceValue(sequenceName){
           var sequenceDocument = db.counters.findAndModify(
              {
                 query:{_id: sequenceName },
                 update: {$inc:{sequence_value:1}},
                 new:true //new 表示返回个性化后的文档
              });
           return sequenceDocument.sequence_value;
        }
        
        
        //使用方式
        db.mycol.insert({"_id":getNextSequenceValue("productid"), "product_name":"Samsung S3","category":"mobiles"})
        
        
    6、MongoDB的副本集配置:
        步骤一:创建多个数据库目录。
                进入/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/目录,创建dbs目录,然后进入dbs目录,
                创建db01、db02、db03、arb目录。
        
        步骤二:启动MongoDB服务。
                ./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db01 --port 27017 --replSet myrs
                ./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db02 --port 27018 --replSet myrs
                ./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db03 --port 27019 --replSet myrs
                ./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/arb --port 30000 --replSet myrs
                
                
        步骤三:使用mongo的shell登录到其中一个服务端。
                ./bin/mongo 10.17.2.61:27017
                
        
        步骤四:在mongo的shell中初始化副本集。
                //创建配置对象。注意host主机地址切勿填写为localhost本地地址,将会导致java客户端连接出异常。
                var config={_id:"myrs",members:[{_id:1,host:"10.17.2.61:27017"},{_id:2,host:"10.17.2.61:27018"},{_id:3,host:"10.17.2.61:27019"}]}
                //初始化。注意只能初始化一次,mongodb会将初始化后的数据写入文件,下次重新启动服务不用再初始化。
                rs.initiate(config)
                
                注意:
                    rs开头表示是对replica set 副本集的操作。initiate方法只运行初始化一次。
                    如果想修改config配置,可以使用rs.reconfig(config:{force:true})来强制更改配置。
                    执行完配置后,可以通过rs.config()来看配置情况,rs.status()来查看集群状态。
                    
                    
        步骤五:添加arbiter仲裁节点。
                arbiter仲裁节点不备份数据,只是再当主服务器宕机时,有仲裁节点来选定从节点哪个变为主节点。
                如果没有仲裁节点,从节点将自己从内部选取,故可以不需要仲裁节点,但要求节点数必须是奇数,如果是偶数则必须要仲裁节点。
                
                rs.addArb("10.17.2.61:30000")
                
                提示:如果需要动态的添加节点或删除节点,可以使用rs.add("host:port")命令来添加副本集节点,
                      删除从节点或者仲裁节点使用rs.remove("host:port")。
                      
        
        步骤六:指定一个主节点。
                默认情况下,当前所以节点都是从节点,可以使用rs.status()来查看状态。
                
                登录需要指定为主节点的mongo的shell客户端,执行命令rs.isMaster() 来提升当前节点为主节点。
                
                提示:默认从节点是不可以做读写的,可以设置为运行从节点进行读操作,但写操作是一直都禁止的。
                      登录从节点的mongo的shell客户端,执行命令 rs.slaveOk(),注意只是针对当前会话的设置,
                      如果退出重进,需要重新执行这个命令。
                
                
        步骤七:测试。
                可以将主节点的进程kill掉,可以看到从节点有一个自动提升为主节点。
                
                提升:当有节点宕机后,其他节点还是会定时的发布心跳来检测节点是否恢复,会打印大量的日志信息,需要处理好日志级别。
                
        
        步骤八:java客户端连接副本集。
                Builder builder = MongoClientOptions.builder();
                builder.serverSelectionTimeout(3000000);
                builder.requiredReplicaSetName("myrs");
                builder.readConcern(readCon);
                builder.writeConcern(writeCon);
                MongoClientOptions op = builder.build();
            
                /*多个副本集节点,指定多个ip地址。必须有一一列举副本集节点的ip,
                 *MongoClient客户端之后在指定ip的副本集读取和操作数据,如果没有指定,即使他也是副本集的一个,也不会拿取数据。
                 *下面的ip中,即使有一个ip的服务宕机了,也不影响操作,可以继续提供服务。
                 */
                List<ServerAddress> list = new ArrayList<ServerAddress>();
                list.add(new ServerAddress("10.17.2.61", 27017));
                list.add(new ServerAddress("10.17.2.61", 27018));
                list.add(new ServerAddress("10.17.2.61", 27019));
                list.add(new ServerAddress("10.17.2.61", 30000));
                MongoClient client = new MongoClient(list, op);
                
                
                
                
        
                
        


http://www.ppmy.cn/ops/161555.html

相关文章

Spring Cloud源码 - Eureka源码原理分析

Eureka源码原理分析 文章目录 Eureka源码原理分析一&#xff1a;启动过程源码1&#xff1a;初始化环境2&#xff1a;初始化上下文2.1&#xff1a;加载erueka-server配置文件2.2&#xff1a;构造实例信息管理器2.3&#xff1a;初始化erueka-client2.4&#xff1a;处理注册相关的…

VC++零基础入门之系列教程 【附录E MFC快速参考指南】

附录E MFC快速参考指南 E.1 创建窗口 使用M F C CWnd wnd; W n d . C r e a t e E x ( E xSt y l e , C l a s s N a m e , Wi n d o w N a m e , S t y l e , x , y, Wi d t h , H e i g h t , P a r e n t , M e n u , P a r a m ) ; 使用A P I HWND hwnd=::CreateWi n d …

LeetCode--124. 二叉树中的最大路径和

124. 二叉树中的最大路径和 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的…

《论模型驱动架构设计方法及其应用》审题技巧 - 系统架构设计师

软件测试工程师软考论文写作框架 一、考点概述 “模型驱动架构设计及其应用”这一论题&#xff0c;主要考察了考生对模型驱动架构设计&#xff08;MDA&#xff09;这一先进软件设计方法的理解与应用能力。论题涵盖了MDA的基本概念、核心要素、实施流程及在实际项目中的应用等…

【C++】深入理解List:双向链表的应用

凭时间赢来的东西&#xff0c;时间肯定会为之作证。 前言 这是我自己学习C的第七篇博客总结。后期我会继续把C学习笔记开源至博客上。 上一期笔记是关于C的vector类知识&#xff0c;没看的同学可以过去看看&#xff1a;【C】探索Vector&#xff1a;灵活的数据存储解决方案-CS…

飞腾腾锐D2000 + OpenHarmony 4.1release部署deepseek大模型

简介 1.1 飞腾腾锐D2000 飞腾腾锐D2000是一款面向桌面应用的高性能通用处理&#xff0c;集成8个飞腾自主研发的高能效处理器核FTC663&#xff0c;兼 容64位ARMv8指令集并支持ARM64和ARM32两种执行模式&#xff0c;支持单精度、双精度浮点运算指令和ASIMD处理 指令&#xff0c;主…

面试加分项:JVM 锁优化和逃逸分析详解

1 锁优化 JVM 在加锁的过程中&#xff0c;会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。 1.1 自旋锁和自适应自旋 现在大多的处理器都是多核处理器 &#xff0c;如果在多核心处理器&#xff0c;有让两个或者以上的线程并行执行&#xff0c;我们可以让一个…

Linux内核,slub分配流程

我们根据上面的流程图&#xff0c;依次看下slub是如何分配的 首先从kmem_cache_cpu中分配&#xff0c;如果没有则从kmem_cache_cpu的partial链表分配&#xff0c;如果还没有则从kmem_cache_node中分配&#xff0c;如果kmem_cache_node中也没有&#xff0c;则需要向伙伴系统申请…