当前位置: 首页 > news >正文

MongoDB私人学习笔记

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

此笔记主要是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);
                
                
                
                
        
                
        

相关文章:

MongoDB私人学习笔记

俗话说“好记性不如烂笔头”&#xff0c;编程的海洋如此的浩大&#xff0c;养成做笔记的习惯是成功的一步&#xff01; 此笔记主要是ZooKeeper3.4.9版本的笔记&#xff0c;并且笔记都是博主自己一字一字编写和记录&#xff0c;有错误的地方欢迎大家指正。 一、基础知识&#xf…...

C++---了解STL

上节学习了模板&#xff0c;那么就得谈到C的标准模板库STL。 C98&#xff1a;以模板方式重写了C标准库&#xff0c;引入了STL(标准模板库)。 1.概念 STL(Standard template Libarary)标准模板库&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&am…...

智能自动化新纪元:AI与UiPath RPA的协同应用场景与技术实践

智能自动化新纪元&#xff1a;AI与UiPath RPA的协同应用场景与技术实践 引言 在数字化转型的浪潮中&#xff0c;企业对于自动化技术的需求已从简单的任务执行转向更复杂的智能决策。传统RPA&#xff08;Robotic Process Automation&#xff09;通过模拟人类操作处理重复性任务…...

2025年2月科技热点深度解析:AI竞赛、量子突破与开源革命

引言 2025年的科技领域持续呈现爆发式增长&#xff0c;AI大模型竞争白热化、量子计算商业化加速、开源工具生态繁荣成为本月最受关注的议题。本文结合最新行业动态&#xff0c;从技术突破、商业布局到开发者生态&#xff0c;全面解析当前科技热点&#xff0c;为读者提供深度洞…...

计算机网络————(三)

前文二 前文一 Websocket协议 是一种存在TCP协议之上的协议 当客户端需要了解服务器是否更新就需要不断给客户端发送请求询问是否更新&#xff0c;这行会造成服务端压力很大 而Websocket相当于服务器一旦更新了就会给客户端发送消息表明自己更新了&#xff0c;类似客户端订阅…...

请谈谈 React 中的状态管理,如何使用 Context API 和 Redux 进行状态管理?

一、Context API 深度应用 1. 核心实现原理 通过createContext创建上下文对象&#xff0c;使用Provider组件包裹需要共享状态的组件树&#xff0c;子组件通过useContext Hook或Consumer组件消费数据。 代码示例&#xff08;主题切换场景&#xff09;&#xff1a; // 创建上…...

【考研】复试相关上机题目

文章目录 22机试回忆版1、判断燃气费描述输入格式输出格式输入样例输出样例 C o d e Code Code 2、统计闰年数量描述输入格式输出格式输入样例输出样例 C o d e Code Code 3、打印图形描述输入格式输出格式 C o d e Code Code 4、密文数据描述输入格式输出格式输入样例输出样例…...

利用机器学习实现实时交易欺诈检测

以下是一个基于Python的银行反欺诈AI应用示例代码,演示如何利用机器学习实现实时交易欺诈检测。该示例使用LightGBM算法训练模型,并通过Flask框架构建实时检测API: python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preproc…...

Modelfile配置说明

参数说明翻译 参数描述值类型示例用法mirostat启用Mirostat采样以控制困惑度。&#xff08;默认&#xff1a;0&#xff0c;0禁用&#xff0c;1Mirostat&#xff0c;2Mirostat 2.0&#xff09;intmirostat 0mirostat_eta影响算法对生成文本反馈的响应速度。较低的学习率将导致调…...

labview实现有符号位16进制转二进制补码转真值

今天在用一个采集模块时&#xff0c;发现读出寄存器的数据是不同的&#xff0c;它有两种范围&#xff0c;一个时十六进制整型&#xff0c;一种是有符号位十六进制&#xff0c;对应的量程和范围也是不同的&#xff0c;针对之前读取温度没有出现负数的情况&#xff0c;应该是转成…...

浏览器深度解析:打造极速、安全、个性化的上网新体验

在数字化时代,浏览器作为我们获取信息、娱乐休闲的重要工具,其性能与功能直接影响着我们的上网体验。今天,我将为大家介绍一款备受好评的浏览器——Yandex浏览器,并深入解析其独特功能与优势,帮助大家更好地了解并选择这款上网神器。 一、知名公司背书,开源项目融合 Yan…...

JavaScript 简单类型与复杂类型-堆和栈

深入理解JavaScript中的简单类型&#xff08;基本数据类型&#xff09;与复杂类型&#xff08;引用数据类型&#xff09;如何在内存中存储对于编写高效、无误的代码至关重要。本文将探讨这两种类型的差异&#xff0c;以及它们在内存中的存储机制——栈&#xff08;Stack&#x…...

【AI+智造】DeepSeek价值重构:当采购与物控遇上数字化转型的化学反应

作者&#xff1a;Odoo技术开发/资深信息化负责人 日期&#xff1a;2025年2月24日 引言&#xff1a;从事企业信息化工作16年&#xff0c;我见证过无数企业从手工台账到ERP系统的跨越。但真正让采购和物控部门脱胎换骨的&#xff0c;是融合了Deepseek AI的Odoo数字化解决方案——…...

基于YOLO11深度学习的苹果叶片病害检测识别系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

mapbox添加自定义图片绑定点击事件,弹窗为自定义组件

一、首先构建根据后端返回的数据构建geojson格式的数据&#xff0c;点位的geojson数据格式&#xff1a; {"type": "FeatureCollection","features": [{"type": "Feature","geometry": {"type": "…...

SVT-AV1接入ffmpeg说明

一 编译集成 Files v2.3.0 Alliance for Open Media / SVT-AV1 GitLab cd /SVT-AV1/Build/linux/ ./build.sh make install GitHub - FFmpeg/FFmpeg: Mirror of https://git.ffmpeg.org/ffmpeg.git ./configure --enable-libsvtav1 --enable-gpl --extra-ldflags-L/usr/loca…...

基于 C++ Qt 的 Fluent Design 组件库 QFluentWidgets

简介 QFluentWidgets 是一个基于 Qt 的 Fluent Designer 组件库&#xff0c;内置超过 150 个开箱即用的 Fluent Designer 组件&#xff0c;支持亮暗主题无缝切换和自定义主题色。 编译示例 以 Qt5 为例&#xff08;Qt6 也支持&#xff09;&#xff0c;将 libQFluentWidgets.d…...

OpenCV(6):图像边缘检测

图像边缘检测是计算机视觉和图像处理中的一项基本任务&#xff0c;它用于识别图像中亮度变化明显的区域&#xff0c;这些区域通常对应于物体的边界。是 OpenCV 中常用的边缘检测函数及其说明: 函数算法说明适用场景cv2.Canny()Canny 边缘检测多阶段算法&#xff0c;检测效果较…...

多模态人物视频驱动技术回顾与业务应用

一种新的商品表现形态&#xff0c;内容几乎存在于手淘用户动线全流程&#xff0c;例如信息流种草内容、搜索消费决策内容、详情页种草内容等。通过低成本、高时效的AIGC内容生成能力&#xff0c;能够从供给端缓解内容生产成本高的问题&#xff0c;通过源源不断的低成本供给倒推…...

星海智算+ DeepSeek-R1:技术突破与行业应用的协同革新

一、前言 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变着商业和社会的方方面面。最近爆火的DeepSeek-R1系列模型&#xff0c;以其强大的推理能力和在中文的推理、代码和数学任务高效的性能得到了全球用户的热议。该模型不仅在多项专…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...