个人博客 毕业设计3-mongoDB

一、概述

MongoDB 是一个跨平台的,面向文档(文档相当于数据库中的一行)的数据库,是当前 NoSQL 数据库产品中最热门的一种。它介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的产品。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以 存储比较复杂的数据类型。

数据库分为关系型数据库和非关系型数据库

  • 关系型数据库:表与表之间有关系
  • 非关系型数据库:表与表之间没有关系

特点

mongodb一般用于以下两个特点的场景

  • 数据量大
  • 价值较低(比如贴吧,回复那么多,就算帖子丢了影响也不大,但是丢的频率不高)

体系结构

MongoDB 的逻辑结构是一种层次结构。主要由:
文档(document)、集合(collection)、数据库(database)这三部分组成的。逻辑结构是面 向用户的,用户使用 MongoDB 开发应用程序使用的就是逻辑结构。

  • MongoDB 的文档(document),相当于关系数据库中的一行记录。
  • 多个文档组成一个集合(collection),相当于关系数据库的表。
  • 多个集合(collection),逻辑上组织在一起,就是数据库(database)。
  • 一个 MongoDB 实例支持多个数据库(database)
    在这里插入图片描述
    当然,只是像而已

基本类型

  • null:用于表示空值或者不存在的字段,{“x”:null}
  • 布尔型:布尔类型有两个值true和false,{“x”:true}
  • 数值:shell默认使用64为浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用 NumberInt(4字节符号整数)或NumberLong(8字节符号整数), {“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
  • 字符串:UTF-8字符串都可以表示为字符串类型的数据,{“x”:“呵呵”}
  • 日期:日期被存储为自新纪元依赖经过的毫秒数,不存储时区,{“x”:new Date()}
  • 正则表达式:查询时,使用正则表达式作为限定条件,语法与JavaScript的正则表达式相 同,{“x” : / [abc]/}
  • 数组:数据列表或数据集可以表示为数组,{“x”: [“a“,“b”,”c”]}
  • 内嵌文档:文档可以嵌套其他文档,被嵌套的文档作为值来处理,{“x”:{“y”:3 }}
  • 对象Id:对象id是一个12字节的字符串,是文档的唯一标识,{“x”: objectId() }
  • 二进制数据:二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要 将非utf-字符保存到数据库中,二进制数据是唯一的方式。
  • 代码:查询和文档中可以包括任何JavaScript代码,{“x”:function(){/…/}}

二、安装mongoDB

win

就算是用在docker,也要安装win版的,因为mongodb是客户端和服务器端在一起的。我们要在win用mongoDB的客户端,在linux虚拟机中的docker用mongoDB的服务端。

安装了win的之后,配置环境变量,然后安装docker的mongoDB
在这里插入图片描述
在这里插入图片描述

docker

在docker中安装mongoDB
docker run -di --name=tensquare_mongo -p 27017:27017 mongo

这样就在docker中启动mongoDB服务器了,接下来只要在win中打开mongoDB客户端就可以了

cmd中,mongo 地址号
在这里插入图片描述
这只是个测试啦,启动客户端,当以后再用得时候都是通过Java进行操作而不是小黑框操作的,现在还在学习,所以没办法,只能通过小黑框来进行操作与测试,等熟悉了再通过Java操作

三、使用mongoDB

1、_id是主键

这个很重要,由于是非关系型数据库,所以会自己弄个主键名,叫_id,写id是没用的,一定要写_id。如果不设值,那么新建一个文档(一列)的时候,就会给_id自动赋值,很麻烦,所以我们一般都会自己去给_id赋值

1.5、直接不设类型插入数值,默认double类型

这个看起来虽然没啥问题,但是输出到Java的时候,要注意输出的类型,否则会报错

2、常用命令

条件都是BSON格式的

1)选择与创建数据库

选择与创建数据库是一起的,没有就给你创建,有的话就进入到数据库中
use 数据库名

2)插入数据

db.集合名(表).insert(BSON格式的数据)
BSON类似JSON啦,按JSON来写就行

3)查询数据

db.集合名(表).find()
在这里插入图片描述
多插入几个数据
在这里插入图片描述

根据条件查询

比如只查询userid为103的数据
db.spit.find({userid:'1013'})
在这里插入图片描述

查询符合条件的第一条数据

db.spit.findOne({userid:'1013'})
在这里插入图片描述

limit

db.spit.find().limit(3)
在这里插入图片描述

4)修改与删除

  • db.集合名称.update(条件,修改后的数据):修改数据,让该列数据单纯变为后面的值
  • db.集合名称.update(条件,{$set:{修改后的数据}}):修改数据,更新修改过的值

在这里插入图片描述
在这里插入图片描述

  • db.集合名称.remove(条件):根据条件删除
  • db.spit.remove({}):删除所有
    在这里插入图片描述

5)统计条数

db.spit.count(条件)
在这里插入图片描述

6)模糊查找

根据正则表达式进行模糊查找的,但是这里的下标不需要" ",我也很好奇
/模糊查找字符串/
db.spit.find(条件)
在这里插入图片描述

7)大于、小于、不等于

db.集合名称.find({
    
     "field" : {
    
     $gt: value }}) // 大于: field > value 
db.集合名称.find({
    
     "field" : {
    
     $lt: value }}) // 小于: field < value 
db.集合名称.find({
    
     "field" : {
    
     $gte: value }}) // 大于等于: field >= value 
db.集合名称.find({
    
     "field" : {
    
     $lte: value }}) // 小于等于: field <= value
db.集合名称.find({
    
     "field" : {
    
     $ne: value }}) // 不等于: field != value

查找visits>1000的数据
在这里插入图片描述

8)包含与不包含

db.表.find({列名:{$in:[值1,值2]}})包含
db.表.find({列名:{$nin:[值1,值2]}})不包含
查找userid为1013和1014的数据
在这里插入图片描述

9)多条件连接

spit.表.find({$and:[条件1,条件2]})
spit.表.find({$or:[条件1,条件2]})

visits>1000且<1500的数据

10)列值增长

对原列进行数值增长

让_id=2的visits值+1
db.spit.update({_id:"2"},{$inc:{visits:NumberInt(1)}} )

四、Java操作原生mongoDB

其实还有spring data mongoDB更好用的,但是一层一层地学吧

find()

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.7</version>
</dependency>
@SpringBootTest
class MongodbDemoApplicationTests {
    
    

    @Test
    void contextLoads() {
    
    
        MongoClient client = new MongoClient("192.168.12.128");//连接数据库
        MongoDatabase spitdb = client.getDatabase("spitdb");//打开数据库
        MongoCollection<Document> spit = spitdb.getCollection("spit");//打开表
		
		// db.spit.find()
        FindIterable<Document> documents = spit.find();

        for (Document document: documents) {
    
    
            System.out.println("内容"+document.getString("content"));
            System.out.println("用户ID"+document.getString("userid"));
            System.out.println("浏览量"+document.getInteger("visits"));
            System.out.println("-----------");
        }
        client.close();//关闭
    }

}

这就是相当于find,如果是其他的话

条件查询

查询userid=1013

        //db.spit.find({userid:"1013"})
        BasicDBObject bson = new BasicDBObject("userid","1013");
        FindIterable<Document> documents = spit.find(bson);

查询visits>1000

  //db.spit.find({visits:{$gt:1000}})
  BasicDBObject bson = new BasicDBObject("visits",new BasicDBObject("$gt",1000));
  FindIterable<Document> documents = spit.find(bson);

其实认真一看,其实就是{}相当于new BasicDBObject:的就用,隔开

插入数据

这个插入数据我们看函数
在这里插入图片描述
插入一个数据,对象为Document,那我们就创建一个Document对象。

那么new 一个Document的时候,点击构造函数
在这里插入图片描述
发现又要一个map,那就建立一个map吧

到了map就简单多了,就是下标对值嘛,得到之后传给Document,再insertOne

@SpringBootTest
class MongodbDemoApplicationTests {
    
    

    @Test
    void contextLoads() {
    
    
        MongoClient client = new MongoClient("192.168.12.128");//连接数据库
        MongoDatabase spitdb = client.getDatabase("spitdb");//打开数据库
        MongoCollection<Document> spit = spitdb.getCollection("spit");//打开表

        Map<String,Object> map = new HashMap<>();//3.map,下标固定了
        map.put("_id",6);
        map.put("userid",666);
        map.put("nickname","小强");
        map.put("content","这是依据吐槽的话");
        map.put("publishtime",new Date());//赋好值
        Document document = new Document(map);//2.需要一个map
        spit.insertOne(document);//1.需要一个Document
        
        client.close();

    }
}

在这里插入图片描述

五、spring data mongodb

1、准备

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>tensquare</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>tensquare_spit</artifactId>
    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>tensquare_commom</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>
server:
  port: 9006
spring:
  application:
    name: tensquare-spit
  data:
    mongodb:
      host: 192.168.12.128
      database: spitdb

这样准备就做好了,接下来做其他的

2、实体类/dao/service

@Data
public class Spit implements Serializable {
    
    
    @Id
    private String _id;
    private String content;
    private Date publishtime;
    private String userid;
    private String nickname;
    private Integer visits;
    private Integer thumbup;
    private Integer share;
    private Integer comment;
    private String state;
    private String parentid;
}

public interface SpitDao extends MongoRepository<Spit,String> {
    
    
}

接下来的service和controller,普通的增删改查,都和spring data jpa一样,都这么写

3、注意点

值得一提的是,我们在dao层写的主键类型为string,虽然用cmd窗口看不出类型,但是下个图形化界面后,就能看出了
在这里插入图片描述
第一行是数字类型,剩下都是字符串类型 ,所以如果查1的话,就会出错
在这里插入图片描述

4、点赞

在这里插入图片描述
service

    public void updateThumbup(String id){
    
    
        Spit spit = spitDao.findById(id).get();
        spit.setThumbup(spit.getThumbup()+1);
        spitDao.save(spit);
    }

controller

    @PutMapping("thumbup/{spitId}")
    public Result updateThumbup(@PathVariable String spitId){
    
    
        spitService.updateThumbup(spitId);
        return new Result(true,StatusCode.OK,"点赞成功");
    }

在这里插入图片描述

在这里插入图片描述

效率改进

看那个service层,我们对mongodb进行了2次交互,效率低下,可以用原生的来进行一次交互就可以

    @Autowired
    private MongoTemplate mongoTemplate;
    
    public void updateThumbup(String id){
    
    
        //方式1,效率低
//        Spit spit = spitDao.findById(id).get();
//        spit.setThumbup(spit.getThumbup()+1);
//        spitDao.save(spit);
        //方式2,效率高
        //db.spit.update({"_id":"1"},{$inc:{thumbup:NumberInt(1)}})
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));//{"_id":"1"}
        Update update = new Update();
        update.inc("thumbup",1);//{$inc:{thumbup:NumberInt(1)}}
        mongoTemplate.updateFirst(query,update,"spit");//db.spit.update({"_id":"1"},{$inc:{thumbup:NumberInt(1)}})
    }

这样看挺正常的,但是忽略了一个点

重复点赞

一个用户只能点一次赞而已,但是要记录哪个用户点赞,放在数据库压力太大了,所以我们可以放在redis中

导入redis包和修改yml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  redis:
    host: 192.168.12.128

修改controller

    @Autowired
    private RedisTemplate redisTemplate;
    
    @PutMapping("thumbup/{spitId}")
    public Result updateThumbup(@PathVariable String spitId){
    
    
        //判断用户是否点过赞
        //由于没有做验证,所以用户ID写死先
        String userid = "123";
        if (redisTemplate.opsForValue().get("thumbup_"+userid+"_"+spitId)!=null){
    
    
            return new Result(false,StatusCode.REPERROR,"不能重复点赞");
        }
        spitService.updateThumbup(spitId);
        redisTemplate.opsForValue().set("thumbup_"+userid+"_"+spitId,"1");
        return new Result(true,StatusCode.OK,"点赞成功");
    }

在这里插入图片描述

5、发布吐槽

在这里插入图片描述
眨眼一看就是普通的添加,但是我们还需要对其进行初始化,还有根据是否有父节点回复

    public void add(Spit spit){
    
    
        spit.set_id(idWorker.nextId()+"");
        spit.setPublishtime(new Date());//发布时间
        spit.setVisits(0);//浏览量
        spit.setShare(0);//分享数量
        spit.setThumbup(0);//点赞数
        spit.setComment(0);//回复数
        spit.setState("1");//状态码
        //如果有父节点
        if (spit.getParentid()!=null&&"".equals(spit.getParentid())){
    
    
            //db.spit.update({"_id":xxx},{$inc:{comment:NumberInt(1)}})
            Query query = new Query();
            query.addCriteria(Criteria.where("_id").is(spit.getParentid()));
            Update update = new Update();
            update.inc("comment",1);
            mongoTemplate.updateFirst(query,update,"spit");
        }
        spitDao.save(spit);
    }

虽然现在还没有做那个吐槽下面接吐槽,就是根据是否有父节点让回复数+1,这个功能还没实现(好奇课程为啥不实现。。)
在这里插入图片描述
在这里插入图片描述
代码:https://github.com/E-10000/tensquare_demo/tree/master

猜你喜欢

转载自blog.csdn.net/yi742891270/article/details/109641824