~关注我 带你看更多精品技术和面试必备 想要进修一下基础的可以加群
号码 1153132260
1 简介:
MongoDB是一个基于分布式文件存储的数据库。由C 语言编写。MongoDB是一个介于关系数据库和非关系数据库之间的产品, 它支持的数据结构非常松散,是类似json的bson,含义为Binary JSON(二进制JSON)
1.2 特点 (1) 面向集合存储,易存储对象类型的数据 (2) 支持动态查询 (3) 支持完全索引,包含内部对象 (4) 支持复制和故障恢复 (5) 支持多种开发语言 (6) 使用高效的二进制数据存储,包括大型对象 ( 如视频等 )
1.3 适用场景
1 )网站实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及 高度伸缩性。 2 )缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓 存层可以避免下层的数据源过载。 3 )高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对 MapReduce 引擎的内置支持。
2.基本操作
2.1支持的数据类型:
3.1 null null用于表示空值或不存在的字段。示例如下:{"x" : null} 3.2 布尔类型 布尔型数据有 true 和 false两个值。示例如下:{"x" : true} 3.3 数值类型 在 Mongo shell 中,默认使用 64 位浮点型数据。因此,会有以下两种数值形式: {"x" : 2.32}// 或 {"x" : 2} 对于整数类型,可以使用 NumberInt()( 位有符号整型 ) 或 NumberLong()(8 位有符号整型 ) 方法进行转 换。示例如下: {"x" : NumberInt(2)} {"x" : NumberLong(2)} 3.4 字符串 MongoDB 中字符串类型使用 UTF-8 编码的字符表示。示例如下: {"x" : "123@qq.com"} 3.5 日期类型 MongoDB 中日期使用时间戳表示,单位为毫秒,不存储时区。示例如下: 创建日期对象时应该使用 new Date() ,而非构造函数 Date() 。将构造函数作为函数时返回的日期格式 是字符串,而非日期对象(与 JavaScript 工作机制有关)。 {"x" : new Date()} 3.6 正则表达式 MongoDB 中可使用与 JavaScript 相同的正则表达式进行查询筛选等。示例如下: {"x" : /www/i} 3.7 数组 数据集可以用数组格式存储,与 JavaSript 中的数组表示相同。示例如下: 数组中可以包含不同类型的数据元素,包括内嵌文档和数组等。所有 MongoDB 中键 - 值对支持的数据 类型都可以用做数组的值。 {"x" : ["kaikeba", "kaikeba.com"]} 3.8 内嵌文档 文档中可以嵌套一个子文档。在 MongoDB 文档总大小限制为 16MB ,建议使用子文档的形式组织数 据,子文档查询效率要高于多键查询。示例如下: 文档可以做为键的值,即:内嵌文档。 MongoDB 与关系型数据库相比,最大的优势就是内嵌文档。 与关系型数据库的扁平化数据结构相比,使用内嵌文档可以数据的组织方式更加自然。 {"x" : {"kaikeba" : "kaikeba.com"}} 3.9 _id 和 ObjectId MongoDB 中每个文档都有一个 " id" 键, " id" 可以是任何类型,不指 "_id" 时 MongoDB 会生成一个 ObjectId 对象。。示例如下: ObjectId 是一个 12 字节( 24 个十六进制数字)的存储空间, ObjectId 的 12 字节数据组织方式如下: 对于如下一个 ObjectId ,其各位字符含义为: {"_id" : ObjectId()} 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 时间戳 | 机器码 | PID | 计数器 {"_id" : ObjectId("5444cce6aef53b0f343e2b9b")} /* 上面 ObjectId 各位字符含义如下 */ //5444cce6 ,第 0 〜 3 字节(第 1 〜 8 位)为时间戳 //aef53b ,第 4 〜 6 字节(第 9 〜 14 位)为机器码 //0f34 ,第 7 〜 8 字节(第 15 〜 18 位)为进程 ID //3e2b9b ,第 9 〜 11 字节(第 19 〜 24 位)为自增计数器 3.10 代码 MongoDB 的文档和代码中可以包括 JavaScript 代码。示例如下: {"x" : function() { /* 这里是一段 JavaScript 代码 */} } 3.11 二进制数据 二进制数据是一个二进制字节的字作串,要保存非 UTF-8 字符到数据库中,只能使用十进制数据
4.0常用操作
查看数据库(数据库中至少有一条数据,此时的数据库才会显示出来) >show dbs 切换数据库 >use 数据库名 // 这个指令也可以直接创建数据库,但只有添加数据后, show dbs 才能看到该数据库 查看当前数据库,默认数据库 :test >db 查看所有的数据集 >show collections 删除当前数据库 操作 格式 实例 sql 中的类似语句 等于 {:} db.collectionName.fifind({"by":"java"}).pretty() 相当于 where by = 'java' 小于 {:{$lt:}} db.collectionName.fifind({"likes":{$lt:50}}).pretty() 相当于 where likes < 50 小于或等于 {:{$lte:}} db.collectionName.fifind({"likes":{$lte:50}}).pretty() 相当于 where likes <= 50 大于 {:{$gt:}} db.collectionName.fifind({"likes":{$gt:50}}).pretty() 相当于 where likes > 50 大于或等于 {:{$gte:}} db.collectionName.fifind({"likes":{$gte:50}}).pretty() 相当于 where likes >= 50 不等于 {:{$ne:}} db.collectionName.fifind({"likes":{$ne:50}}).pretty() 相当于 where likes != 50 创建集合(相当于创建表) >db.createCollection("user1") 删除集合 >db.collectionName.drop() 集合重命名 >db.oldCollectionName.renameCollection("newName") 新增数据 >db.collectionName.insert({"key":value,"key":value}) 或 >db.collectionName.save({"key":value,"key":value}) 查询所有数据 >db.collectionName.find() 条件查询 > db.collectionName.find ({ "age" : 26 }) // 查询等值关系 > db.collectionName.find ({ age : {$ gt : 100 }}) // 大于 100 > db.collectionName.find ({ age : {$ gte : 100 }}) // 大于等于 100 > db.collectionName.find ({ age : {$ lt : 150 }}) // 小于 150 > db.collectionName.find ({ age : {$ lte : 150 }}) // 小于等于 150 > db.collectionName.find ({ age : {$ lt : 200 , $ gt : 100 }}) // 大于 100 ,小于 200 如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下 >db.collectionName.find().pretty() and 关系 MongoDB 的 fifind() 方法可以传入多个键 (key) ,每个键 (key) 以逗号隔开,即常规 SQL 的 AND 条件 语法 : >db.collectionName.find({key1:value1, key2:value2}).pretty() or 关系 MongoDB OR 条件语句使用了关键字 $or , 语法格式如下: 语法 : >db.collectionName.find({$or: [ {key1: value1}, {key2:value2}]}).pretty() 示例 : >db.collectionName.find({$or:[{"by":"java"},{"title": "MongoDB 学习 "}]}).pretty() 清空集合数据 >db.collectionName.remove({}) // 条件删除 :remove({key:value}) // 删除满足条件的一条数据 :remove({key:value},1) 查询一条数据 >db.collectionName.findOne(); 查询指定列 > db.collectionName.find ({},{ name : 1 , age : 1 , sex_orientation : true }) 查询指定字段的数据,并去重 > db . collectionName . distinct ( 'sex' ) 对结果集排序 > db.collectionName.find () .sort ({ salary : 1 }) // 升序 > db.collectionName.find () .sort ({ salary : -1 }) // 降序 统计记录数 > db .collectionName.find () .count () 查询限定条数 >db.collectionName.find().limit(number) 使用 limit() 方法来读取指定数量的数据外,还可以使用 skip() 方法来跳过指定数量的数据, skip 方法同样 接受一个数字参数作为跳过的记录条数。 >db.collectionName.find().limit(NUMBER).skip(NUMBER) 更新数据 db.collectionName.update(<query>,<update>,{upsert: <boolean>, multi: <boolean>) query: update 的查询条件 update : update 的对象和一些更新的操作符(如 $,$set... )等,也可以理解为 sql update 查询内 set 后面 的 upsert : 可选,如果不存在 update的记录,是否插入 objNew,true 为插入,默认是 false ,不插入。 multi : 可选, mongodb 默认是 false, 只更新找到的第一条记录,如果这个 参数为true,就把按条件查出 来多条记录全部更新。 示例 : > db.collectionName.update({name: 'tom' },{ $set :{age:23}},false, true )
3 .Java调取mongoDB
第一步:添加mongodb-java-driver驱动包
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.2.2</version> </dependency> </dependencies>
第二步 : 连接数据库并操作数据
public static void main(String[] args) { // 1. 连接到 mongodb 服务 MongoClient mongoClient = new MongoClient("192.168.197.133", 27017); // 2. 连接到数据库 MongoDatabase mongoDatabase = mongoClient.getDatabase("mydb1"); //3. 创建集合 // mongoDatabase.createCollection("student"); // 获得集合 MongoCollection<Document> collection = mongoDatabase.getCollection("users"); //4. 新增 Document document = new Document("stu1name", " 张三 "); document.append("stu1age", 29); document.append("sex", " 男 "); collection.insertOne(document); // 插入多行时,将 document 对象添加到 List 集合中,调取 insertMany() //5. 获得所有文档 FindIterable<Document> documents = collection.find(); MongoCursor<Document> iterator = documents.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } //6. 更新文档 updateOne(),updateMany( 条件表达式,新值表达式 ) // collection.updateMany(Filters.eq("sex"," 男 "),new Document("$set",new Document("name","testzhangsan"))); //7. 删除文档 // 删除 20 岁用户的信息 collection.deleteOne(Filters.eq("age",20)); }
4.mongDB索引
索引是对数据库表中一列或多列 的值进行排序的一种结构。 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个 文件并选取那些符合查询条件的记录。
4.1 创建索引的语法
(1) 默认索引 MongoDB 有个默认的 “ id” 的键,相当于 “ 主键 ” 的角色。集合创建后系统会自动创建一个索引在 “ id” 键上,它是默认索引,索引名叫 “_id_” ,是无法被删除的。我们可以通过以下方式查看: >db.collectionName.getIndexes() (2) 单列索引 在单个键上创建的索引就是单列索引,例如我们要在 Users 集合上给 title 键创建一个单列索引,语 法如下: ( 1 表示正序, -1 逆序) >db.collectionName.createIndex({"title":1}) (3) 组合索引 另外,我们还可以同时对多个键创建组合索引。如下代码创建了按照 “UserId” 正序, “UserName” 逆序的组合索引 : >db.collectionName.createIndex({"userid":1,"username":-1}) (4) 唯一索引 唯一索引限制了对当前键添加值时,不能添加重复的信息。值得注意的是,当文档不存在指定键 时,会被认为键值是 “null” ,所以 “null” 也会被认为是重复的,所以一般被作为唯一索引的键,最好都要 有键值对。 对 “UserId” 创建唯一索引 ( 这时候最后一个参数为 “true”) : >db.collectionName.createIndex({"UserId":1}, { unique: true }); (5)TTL 索引 TTL 指生命周期的意思。即存储的 document 存储带有过期时间属性,超过生命周期自己主动删除。 像日志数据、系统自己主动产生的暂时数据、会话数据等均符合这一场景。 构建方式如: db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } ) (6) 删除索引 新手常陷入的误区是,认为集合被删除,索引就不存在了。关系型数据库中,表被删除了,索引也 不会存在。在 MongoDB 中不存在删除集合的说法,就算集合数据清空,索引都是还在的,要移除索引 还需要手工删除。 >db.collectionName.dropIndexes() 删除集合指定索引 >db.collectionName.dropIndex(" 索引名称 ") 说明 :drop() 集合时,索引也会删除, remove() 集合时,索引仍然存在
5 .mongoDB备份与恢复
5.1 mongodump命令来备份数据
该命令可以导出所有数据到指定目录中。 mongodump 命令可以通过参数指定导出的数据量级转存的服务器。 语法 >mongodump -h dbhost -d dbname -o dbdirectory -h : MongDB 所在服务器地址,例如: 127.0.0.1 ,当然也可以指定端口号: 127.0.0.1:27017 -d : 需要备份的数据库实例,例如: test l--o 备份的数据存放位置,例如: c:datadump ,当然该目录需要提前建立,在备份完成后,系统自 动在 dump 目录下建立一个 test 目录,这个目录里面存放该数据库实例的备份数据。 示例 在本地使用 27017 启动你的 mongod 服务。打开命令提示符窗口,进入 MongoDB 安装目录的 bin 目录 输入命令 > mongodump: (不指定在当前目录保存) 执行以上命令后,客户端会连接到 ip 为 127.0.0.1 端口号为 27017 的 MongoDB 服务上,并备份所有数 据到 bin/dump/ 目录中。命令输出结果如下:
5.2 MongoDB 数据恢复
mongodb 使用 mongorestore 命令来恢复备份的数据。 语法 >mongorestore -h <hostname><:port> -d dbname <path> --host <:port>, -h <:port> : MongoDB 所在服务器地址,默认为: localhost:27017 --db , -d : 需要恢复的数据库实例,例如: test ,当然这个名称也可以和备份时候的不一样,比如 test2 --drop : 恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都 会被删除,慎用哦!
6 集群搭建
集群搭建方式之一就是mongoDB复制集,即一组mongod的进程。他们维护同一个数据集合。复制集 保证了数据的可靠性和高读取能力。
6.1 机制 一组复制集就是一组 mongod 实例管理同一个数据集,实例 key 在不同的机器上,实例包含主实例 (primary), 接受所有的写操作,其他的属于副本实例 (Secondary), 从服务器保持与主服务器数据同步,类 似于 redis 中的主从复制。 每个复制集还有一个仲裁者 (Arbiter), 仲裁者的任务就是通过心跳机制来确认集群中集合的数量,并 在选举主服务器的过程中进行裁决。仲裁者并不存储数据,性质等价于 redis 中的哨兵机制。
8.2 架构 在数据承载节点中,一个且只有一个成员被视为主节点,而其他节点则被视为辅助节点。节点接收所有 写入操作,一个副本集只能有一个主实例能够写入,主节点记录所有变更到它的记录 辅助节点复制主节点的 oplog 并将操作应用于数据集。 仲裁员不维护数据集,仲裁器的目的是通过响应其 他副本集成员的心跳和选择请求来维护副本集中的仲裁。 因为它们不存储数据集,所以仲裁器是提供副本集仲裁功能的一种好方法。 与具有数据集的完全功能副本集成员相比,仲裁器的资源成本更低,如果副本集的成员数为偶数,则添 加一个仲裁器以在初选中获得多数票。 当一个主服务器在超过配置的周期(默认为 10 秒)内未与该组的其他成员通信时,符合条件的辅助服 务器将要求选择将其自身指定为新的主服务器。集群试图完成新的初选并恢复正常操作。 8.3 搭建步骤 (1) 准备三台虚拟机服务器,并各自安装好 mongoDB 注:为了保证复制集中三个服务器之间正常连接,请保证三个服务器的防火墙都已关闭! 192.168.132:27017 192.168.133:27017 192.168.134:27017 (2) 修改 mongodb.conf 文件,添加 replSet 配置 ( 三台都需要修改成同一个名称 ) ,然后启动服务器 replSet=rep1 (3) 初始化复制集 登录任意一台执行初始化操作 说明 : _id 指复制集名称, members 指复制集服务器列表,数组中的 _id 是服务器唯一的 id,host 服务器主 机 ip # 复制集名称 rs.initiate({_id:'rep1',members:[{_id:1,host:'192.168.197.132:27017'}, {_id:2,host:'192.168.197.133:27017'},{_id:3,host:'192.168.197.134:27017'}]}) (4) 查看集群状态 (5) 测试 # 添加数据 db.users.insert({"name":"lisi","age":11}) # 查询数据 db.users.find() # 切换到从数据库查询数据 如果不允许查询,是因为默认情况下从数据库是不允许读写操作的,需要设置。 >rs.slaveOK() 执行该命令后可以查询数据 (6) 测试复制集主从节点故障转移功能 # 关闭主数据库 , 注意从数据库的变 >db.shutdownServer() (7) 主复制集添加仲裁者 (arbiter) 现在我们的环境是一主两从,仲裁者对偶数集群有效。需要停止一个从机,在主服务器中运行下面命令 在一主一从关系中,任意节点宕机都无法选举出主节点,无法提供写操作,此时需要加入仲裁者节点即 可。 rs.remove("ip: 端口号 ") // 删除从节点 在一主一从关系中,任意节点宕机都无法选举出主节点,无法提供写操作,此时需要加入仲裁者节点即 可。 rs.addArb("ip: 端口号 ")
累,点个赞可否 么么哒~
~拜了个拜