MongoDB数据库

一、在Ubuntu下进行MongoDB安装步骤:

1.MongoDB可以直接用apt-get命令进行安装。
sudo apt-get install mongodb
2.mongodb服务常用命令
  • systemctl status mongodb // 查看状态
  • systemctl start mongodb //启动
  • systemctl restart mongodb //重新启动
  • systemctl stop mongodb //停止
  • mongo 或者 mongo ip地址:端口号 //进入数据库
  • mongo --host=127.0.0.1 --port=27017

二、重启系统以后mongo程序要自己重新手动启动,步骤如下:

1.运行“locate mongo”命令查看系统默认把mongo装到了哪里,这里主要关注三个东西。
  • 一个是名为“mongod”的程序的位置(他相当于mongo数据库的Server,需要一直在后台运行,我的路径:/usr/bin/mongod);

  • 一个是mongo 数据库文件的位置(我的路径:/var/lib/mongodb/);

  • 一个是mongo的log日志的位置(我的路径:/var/log/mongodb/mongodb.log)。

2.先进入mongod所在的目录(/usr/bin/mongod),然后运行“./mongod --dbpath /var/lib/mongodb/ --logpath /var/log/mongodb/mongodb.log --logappend &”
  • --dbpath:指定mongo的数据库文件在哪个文件夹
  • --logpath:指定mongo的log日志是哪个,这里log一定要指定到具体的文件名
  • --logappend:表示log的写入是采用附加的方式,默认的是覆盖之前的文件
  • &:表示程序在后台运行

注意:如果是系统非正常关闭,这样启动会报错,由于mongodb自动被锁上了,这是需要进入mongodb数据库文件所在的目录(/var/lib/mongodb/),删除目录中的mongodb.lock文件,然后再进行上述操作。

三、使用MongoDB

1.进入mongodb数据库
  • mongo
  • mongo ip地址:端口号 //进入数据库
  • mongo --host=127.0.0.1 --port=27017
2.常用操作命令:

show dbs:显示数据库列表
show collections:显示当前数据库中的集合(类似关系数据库中的表table)
show users:显示所有用户
use yourDB:切换当前数据库至yourDB
db.help():显示数据库操作命令
db.yourCollection.help() :显示集合操作命令,yourCollection是集合名
MongoDB没有创建数据库的命令,如果你想创建一个“School”的数据库,先运行use School命令,之后做一些操作(如:创建聚集集合db.createCollection('teacher')),这样就可以创建一个名叫“School”的数据库。截图如下:

下面以一个School数据库为例,在School数据库中创建两个集合teacher和student,并对student集合中的数据进行增删改查基本操作(集合Collection相当于关系型数据库中的表table)。

  • 切换到School数据库

use School #切换到School数据库。MongoDB 无需预创建School数据库,在使用时会自动创建

  • 创建Collection

db.createCollection('teacher') #创建一个聚集集合。MongoDB 其实在插入数据的时候,也会自动创建对应的集合,无需预定义集合

  • 插入数据

与数据库创建类似,插入数据时也会自动创建集合。
插入数据有两种方式:insert和save。

db.student.insert({_id:1, sname: 'zhangsan', sage: 20}) #_id可选
db.student.save({_id:1, sname: 'zhangsan', sage: 22}) #_id可选

这两种方式,其插入的数据中_id字段均可不写,会自动生成一个唯一的_id来标识本条数据。而insert和save不同之处在于:在手动插入_id字段时,如果_id已经存在,insert不做操作,save做更新操作;如果不加_id字段,两者作用相同都是插入数据。

  • 查找数据

db.youCollection.find(criteria, filterDisplay)

  • criteria :查询条件,可选
  • filterDisplay:筛选显示部分数据,如显示指定列数据,可选(当选择时,第一个参数不可省略,若查询条件为空,可用{}做占位符,如下例第三句)
  • db.student.find() #查询所有记录。相当于:select * from student
  • db.student.find({sname: 'lisi'}) #查询sname='lisi'的记录。相当于: select * from student where sname='lisi'
  • db.student.find({},{sname:1, sage:1}) #查询指定列sname、sage数据。相当于:select sname,sage from student。sname:1表示返回sname列,默认_id字段也是返回的,可以添加_id:0(意为不返回_id)写成{sname: 1, sage: 1,_id:0},就不会返回默认的_id字段了
  • db.student.find({sname: 'zhangsan', sage: 22}) #and 与条件查询。相当于:select * from student where sname = 'zhangsan' and sage = 22
  • db.student.find({$or: [{sage: 22}, {sage: 25}]}) #or 条件查询。相当于:select * from student where sage = 22 or sage = 25

查询操作类似,这里只给出db.student.find({sname: 'lisi'})查询的截图,如下:


  • 修改数据

db.youCollection.update(criteria, objNew, upsert, multi )

  • criteria: update的查询条件,类似sql update查询内where后面的
  • objNew : update的对象和一些更新的操作符(如$set)等,也可以理解为sql update查询内set后面的upsert ,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi: mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。默认false,只修改匹配到的第一条数据。

其中criteria和objNew是必选参数,upsert和multi可选参数。举例如下:

db.student.update({sname: 'lisi'}, {$set: {sage: 30}}, false, true) #相当于:update student set sage =30 where sname = 'lisi';

  • 删除数据

db.student.remove({sname: 'chenliu'}) #相当于:delete from student where sname='chenliu'

  • 退出shell命令模式

输入exit或者Ctrl+C退出shell命令模式

四、springBoot中使用MongoDB

1.pom文件
<!--mongo-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
2.yml文件配置
spring.data.mongodb.uri=mongodb://zzq:123456@localhost:27017/mydb

或者

spring:
  data:
    mongodb:
      uri: mongodb://192.168.1.87:49901/ums

3.Controller层

@Api(tags = "文件上传下载API")
@RequestMapping("/api/file/")
@RestController
public class FileController {

    @Autowired
    private FileService fileService;


    @ApiOperation("文件上传")
    @PostMapping
    public Result uploadFile(@RequestBody MultipartFile file, HttpServletRequest request) {
        return Result.ok(fileService.uploadFile(file, request));
    }

    @ApiOperation("文件下载")
    @GetMapping
    public Result downloadFile(@RequestParam("ObjectId") String ObjectId, HttpServletResponse response) {
        fileService.downloadFile(ObjectId, response);
        return Result.ok();
    }

    @ApiOperation("文件删除")
    @PutMapping
    public Result deleteFile(@RequestParam("ObjectId") String ObjectId) {
        fileService.deleteFile(ObjectId);
        return Result.ok();
    }
}
4.Service层
@Service
public class FileService {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileService.class);

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private MongoDbFactory mongodbfactory;

    public Object uploadFile(MultipartFile file, HttpServletRequest request) {
        try {
            ObjectId objectId = null;
            // 获得提交的文件名
            String fileName = file.getOriginalFilename();
            // 获得文件类型
            String contentType = file.getContentType();
            BufferedImage image = isImage(file.getInputStream());
            int angle = 0;
            if(image != null){
                //获取需要旋转的角度  angle为0说明图片不需要进行旋转  直接返回图片
                angle = ImageUtils.getRotateAngleForPhoto(file.getInputStream());
            }
            if(angle == 0){
                // 获得文件输入流
                InputStream ins = file.getInputStream();
                // 将文件存储到mongodb中,mongodb 将会返回这个文件的objectId
                objectId = gridFsTemplate.store(ins, fileName, contentType);
                ins.close();
            } else {
                String name = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "jpg";
                image = ImageUtils.rotate(image, angle);
                // 将文件存储到mongodb中,mongodb 将会返回这个文件的objectId
                objectId = gridFsTemplate.store(ImageUtils.getImageStream(image), name, "image/jpeg");
                image = null;
            }
            return objectId.toString();
        } catch (Exception e) {
            LOGGER.error(MsgEnum.UPLOAD_ERROR.getMessage(), e);
            throw new ServerException(MsgEnum.UPLOAD_ERROR);
        }
    }

    /**
     * 判断文件是否为图片
     *
     * @param in
     * @return
     */
    public static BufferedImage isImage(InputStream in) {
        try {
            BufferedImage image = ImageIO.read(in);
            return image;
        } catch (IOException e) {
            return null;
        }
    }

    public void downloadFile(String objectId, HttpServletResponse response) {
        DBObject query = new BasicDBObject("_id", new ObjectId(objectId));
        GridFS gridFS = new GridFS(mongodbfactory.getLegacyDb());
        GridFSDBFile file = gridFS.findOne(query);
        try {
            if (file == null) {
                response.getWriter().write("文件已经不存在啦!");
            } else {
                // 通知浏览器进行文件下载
                response.setContentType(file.getContentType());
                String fileName = URLEncoder.encode(file.getFilename(), "UTF-8");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName+"\"");
                file.writeTo(response.getOutputStream());
            }
        } catch (Exception e) {
            LOGGER.error(MsgEnum.DOWNLOAD_ERROR.getMessage(), e);
            throw new ServerException(MsgEnum.DOWNLOAD_ERROR);
        }

    }

    public void deleteFile(String objectIdString) {
        ObjectId objectId = new ObjectId(objectIdString);
        GridFS gridFS = new GridFS(mongodbfactory.getLegacyDb());
        gridFS.remove(objectId);
    }
}
  • ImageUtils
public final class ImageUtils {

    /**
     * 获取图片中需要调整的角度信息
     * 图片的 exif 信息,
     *
     * @param in
     * @return
     */
    public static int getRotateAngleForPhoto(InputStream in) {
        int angle = 0;
        Metadata metadata = null;
        try {
            metadata = ImageMetadataReader.readMetadata(in);
//          todo  getFirstDirectoryOfType 方法是否有问题?获取第一个还是获取多个处理?
            ExifDirectoryBase directory = metadata.getFirstDirectoryOfType(ExifDirectoryBase.class);
            if (directory != null && directory.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) {
//                原图片的方向信息
                int orientation = directory.getInt(ExifDirectoryBase.TAG_ORIENTATION);
                switch (orientation) {
                    case 6: // 6旋转90
                        angle = 90;
                        break;
                    case 3: //3 旋转180
                        angle = 180;
                        break;
                    case 8: //8旋转270
                        angle = 270;
                        break;
                }
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return angle;
    }


    /**
     * 调整图片角度
     *
     * @param image
     * @param angle
     * @return
     */
    public static BufferedImage rotate(BufferedImage image, int angle) {
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        //计算新图片的大小
        Rectangle rectangle = calcRotatedSize(
                new Rectangle(new Dimension(width, height)),
                angle);
        BufferedImage res = new BufferedImage(rectangle.width, rectangle.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = res.createGraphics();
        //转换图片
        graphics2D.translate(
                (rectangle.width - width) / 2,
                (rectangle.height - height) / 2);
        graphics2D.rotate(Math.toRadians(angle), width / 2, height / 2);
        graphics2D.drawImage(image, null, null);
        graphics2D.dispose();
        return res;
    }

    private static Rectangle calcRotatedSize(Rectangle src, int angle) {
        // 角度超过90
        if (angle >= 90) {
            if (angle / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angle = angle % 90;
        }
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angle) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angle)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

    public static InputStream getImageStream(BufferedImage bimage) {
        InputStream is = null;
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ImageOutputStream imOut;
        try {
            imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(bimage, "jpg", imOut);
            is = new ByteArrayInputStream(bs.toByteArray());
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return is;
    }
}

推荐阅读更多精彩内容