随着互联网应用变得越来越复杂数据格式越来越灵活我们常常会遇到这样的困境需求频繁变更增加一个字段就要改表结构ALTER TABLE在海量数据上这简直是噩梦。数据结构复杂想存储一个嵌套的JSON对象得拆分成十几张表查询时要写复杂的JOIN性能堪忧。正是为了解决这些问题NoSQL数据库应运而生而MongoDB便是其中之一。一、什么是NoSQLNoSQL 的全称是Not Only SQL意为“不仅仅是SQL”。它并不是要取代SQL而是为其提供一种补充适用于不同的场景。NoSQL数据库种类繁多主要分为以下几类文档型数据库如MongoDB以灵活的JSON-like文档存储数据键值型数据库如Redis简单的键值对速度极快列族数据库如 Cassandra为大规模数据分析设计图数据库如 Neo4j专注于实体之间的关系它们的共同特点是灵活、易扩展、高性能。二、什么是MongoDB关于MongoDB的介绍、安装具体内容详见下述文章01 MongoDB的概述、应用场景、下载方式、连接方式和发展历史等-阿里云开发者社区https://developer.aliyun.com/article/1611979MongoDB与Reids的差异特性MongoDBRedis核心定位文档型数据库内存型键值数据库数据模型丰富的文档模型(类似 JSON的BSON)简单的键值对值支持多种数据结构存储介质磁盘(内存用于缓存加速)内存(可持久化到磁盘)主要优势灵活性、查询能力、海量数据存储速度(极低延迟)、高并发、原子操作典型用例主数据库、内容管理、用户配置、实时分析缓存、消息队列、会话存储、实时排行榜三、与Mysql对比进行MongoDB的理解概念对比概念MongoDB (文档数据库)MySQL (关系型数据库)数据格式类似JSON的文档灵活嵌套表格严格的行和列例子{_id: 1, name: Alice, hobbies: [唱歌, 游泳] }id: 1, name: Alice hobbies需拆到另一张表适合场景数据结构多变、嵌套复杂如用户画像、日志结构固定、需要强一致性如订单、账户术语对比MySQL 术语MongoDB 对应术语区别说明数据库 (Database)数据库 (Database)概念相同表 (Table)集合 (Collection)MySQL 表有固定结构MongoDB 集合无固定结构行 (Row)文档 (Document)MongoDB 的文档可以嵌套其他文档或数组列 (Column)字段 (Field)MongoDB 的字段可以动态增减主键 (Primary Key)_id 字段MongoDB 自动生成唯一 _id外键 (Foreign Key)无原生支持MongoDB 通过手动引用实现关联JOIN 操作$lookup有限支持MongoDB 的关联查询性能较低推荐数据嵌套查询语法对比查询类型MySQL 查询语句MongoDB 查询语句查询所有用户SELECT * FROM users;db.users.find();条件查询年龄18SELECT * FROM users WHERE age 18;db.users.find([ age: { $gt: 18 } ]);关联查询用户订单SELECT u.name, o.order_id FROM users u JOIN orders o ON u.id o.user_id;db.users.aggregate([ { $lookup: { from: orders, localField: _id, foreignField: user_id, as: orders } } ]);四、MongoDB Spring Boot 实现文件存储一两种存储方式MongoDB 提供两种文件存储方式1.GridFS适合大文件16MBMongoDB 单个文档限制自动分块存储支持流式读写2.直接存储小文件Base64/Binary适合小文件16MB简单快捷无需额外配置以下采用GridFS大文件存储的方式进行文件存储。二添加依赖与配置文件!-- mongodb依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-mongodb/artifactId /dependency# application.yml spring: data: mongodb: host: localhost port: 27017 database: test # username: your_user # password: your_pass三代码实践需在controller类中添加import org.springframework.data.mongodb.core.MongoTemplate;Autowired private MongoTemplate mongoTemplate; // 对mongo数据库进行连接使用文件上传PostMapping(upload) public String uploadFile(MultipartFile file) { try (InputStream inputStream file.getInputStream()){ // 1、 创建桶数据库名称 桶名 GridFSBucket bucket GridFSBuckets.create(mongoTemplate.getDb(),file); //2、 设置分片上传的条件 GridFSUploadOptions options new GridFSUploadOptions() .chunkSizeBytes(1024) .metadata(new Document(filename,file.getOriginalFilename())); // 附加的记录信息 // 3、 上传文件 // objectId 是 文件的唯一标识 ( mongodb集合中的主键 “_id”) ObjectId objectId bucket.uploadFromStream(file.getOriginalFilename(), inputStream,options); // 转化成String return objectId.toHexString(); } catch (IOException e) { throw new RuntimeException(e); } }文件预览/下载GetMapping(preview/{id}) public void previewFile(PathVariable(id) String id, HttpServletResponse response) { // 1、 创建桶 GridFSBucket bucket GridFSBuckets.create(mongoTemplate.getDb(),file); // 2、 获取文件主键信息 ObjectId objectId new ObjectId(id); // 3、 查找文件信息 // 查找条件 new BsonDocument(_id, new BsonObjectId(objectId)) GridFSFile file bucket .find(new BsonDocument(_id, new BsonObjectId(objectId))) .first(); if (file null) { // throw new RuntimeException(文件不存在); try { response.sendError(40404,文件不存在); } catch (IOException e) { throw new RuntimeException(e); } } // 文件存在 获取文件流 // 4、 获取文件流 // 设置响应头根据文件类型调整 Content-Type //response.setContentType(file.getMetadata().get(_contentType, application/octet-stream)); response.setHeader(Content-Disposition, inline; filename\ file.getFilename() \); // 5 、将文件流写入响应 try (GridFSDownloadStream downloadStream bucket.openDownloadStream(file.getObjectId())) { try { IOUtils.copy(downloadStream, response.getOutputStream()); } catch (IOException e) { throw new RuntimeException(e); } } }文件删除DeleteMapping(/delete/{id}) public void delete(PathVariable String id) { GridFSBucket bucket GridFSBuckets.create(mongoTemplate.getDb(),file); bucket.delete(new ObjectId(id)); }存在判断GetMapping(/{id}) public String get(PathVariable String id) { // 1、 创建桶 GridFSBucket bucket GridFSBuckets.create(mongoTemplate.getDb(),file); // 2、 查找文件信息 查找条件 new BsonDocument(_id, new BsonObjectId(objectId)) GridFSFile file bucket .find(new BsonDocument(_id, new BsonObjectId(new ObjectId(id)))) .first(); if (file ! null) { return 文件存在; } else { return 文件不存在; } }