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;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容