MongDB增删改查+集成springboot

  • Post author:
  • Post category:其他




MongDB – Spring data Jpa



1.mongodb



1.1 简介

1.MongoDB是一个基于分布式文件存储的数据库。
2.MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
3.它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
4.Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
5.MongoDB属于NoSQL数据库,自然也是没有表相关概念的,该数据库存储使用的是集合,集合中存储的是文档(树状结构数据)



1.2 特点

- 高性能
- 易部署
- 易使用
- 非常方便的存储数据



2.安装及navict安装

安装包+破解---->视频
navicat12开始支持mongodb



基本语法

show dbs: 查询所有数据库
use 数据库名: 创建并且选中数据库,数据库已经存在则直接选中
db: 查询当前选择的数据库
db.dropDatabase(): 删除当前选中的数据库
show collections: 查询当前库中的集合
db.createCollection("集合名"): 创建集合
db.集合名.drop(): 删除集合



3.操作



3.1新增

//往集合中新增文档,当集合不存在时会自动先创建集合
db.集合名.insert( 文档 )    往集合中插入一个文档
	例:db.user.insert({id: 1, name: "bunny", age: 20});
(当操作成功时,集合会给文档生成一个**_id**字段,该字段就是文档的主键)



3.2更新

db.集合名.update(
  <query><update>{
        upsert: <boolean>,
        multi: <boolean>,
        writeConcern: <document>
  }
)
简化方法:
更新1个:db.集合名.updateOne( ... )
更新所有:db.集合名.updateMany( ... )

//**query** : update的查询条件,类似sql update查询内where后面的。
//**update** : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
//**upsert** : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
//**multi** : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
//**writeConcern** :可选,抛出异常的级别


	例:db.user.update(
			{
				name:"bunny"
			},
			{$set:{
				age:233
			}},
			{
				multi:true
			}
		);



3.3删除

db.集合名.remove(
  <query>{
        justOne: <boolean>,
        writeConcern: <document>
  }
)

简化方法:
删除1个:db.集合名.deleteOne( ... )
删除所有:db.集合名.deleteMany( ... )

//**query** :(可选)删除的文档的条件。
//**justOne** : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
//**writeConcern** :(可选)抛出异常的级别
	例:db.user.deleteMany(
		{name:"wangwu"}
		);


//remove() 方法 并不会真正释放空间。需要继续执行 db.repairDatabase() 来回收磁盘空间。
db.repairDatabase()
db.runCommand({ repairDatabase: 1 })



3.4 查询

db.集合名.find(query, projection)
//参数1:查询操作符指定查询条件
//参数2:通过0,1来指定是否要,某一列  (映射的列必须同时0或1)

例://查所有
	db.users.find()	
	db.users.find({},{_id:0,name:1})  //只显示name列


3.4.1排序查询
db.users.find({}).sort({字段: 1}) -> 按照字段升序排列
db.users.find({}).sort({字段: -1}) -> 按照字段降序排列

例://按照年龄排序  //1正序,-1倒叙
db.users.find({}).sort({age:1}); //正序


3.4.2分页查询
db.users.find({}).skip(pagesize*(currentpage - 1)).limit(5);

db.users.find({}).sort({id:-1}).skip(0).limit(5); //先进行排序,再分页

//skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。



3.5高级查询



3.5.1比较操作符
//带条件的查询
//>操作
//语法 -> find(     {字段: {比较操作符: 值, ...}}       )
//> 大于 - $gt                 greate than
//< 小于 - $lt                  less 
//>= 大于等于        - $gte       equals
//<=  小于等于       - $lte
//!= 不等            - $ne
//    {$exists: false}  查询指定列存在不存在
//in   {$in: [xx, xx ...]}

例:db.users.find(                                               
		{                                                                 
			age:{$gt:30}                 
		}                                      
	);   

db.users.find({
		name:{
			$in:["dafei","will"]
	}
})


3.5.2逻辑操作符
语法 -> find({列:{逻辑操作符: [条件1, 条件2...]}})

- (&&)- $and
- (||)- $or
- (!)- $not

例://and
db.users.find({
	$and:[
		{age:{$gte:30}},
		{age:{$lte:32}}
	]
})

//or
//查询所有age<28,age>30的文档
db.users.find({
	$or:[
		{age:{$gte:30}},
		{age:{$lte:28}}
	]
})


//$not
//语法: { field: { $not: { <operator-expression> } } }
//$not执行一个逻辑not操作在指定的表达式并查询到不匹配表达式的文档,这包含不包括字段的文档;
$not操作符只会影响其他操作符不能独立检查字段和文档,因此使用$not做逻辑析取和$ne操作测试字段内容


使用$not操作时考虑如下操作:

1.操作$not操作符和其它操作符一致但是会产生一些意想不到的结果,比如数组之类的数据类型;
2.$not操作符不支持$regex正则表达式操作,使用//或者你的驱动接口代替,使用语言的正则表达式功能创建正则表达式对象;


3.5.3模糊查询
//模糊查询
//db.集合.find({列: {$regex: /关键字/}})
//sql: select * from user where name like '%%'
//{name:/xxx/}     --->%xxx%
//{name:/^xxx/} --->xxx%
//{name:/xxx$/} --->%xxx
//{name:/xxx/i}   忽略大小写

例://正则表达式对象
db.users.find({
	name:{$regex:/fei/}
})

//正则表达式字符串
db.users.find({
	name:{$regex:".*fei.*"}
})



3.6 数组查询



3.6.1 添加
//向数组里添加   $push   $addToset
//给dafei添加一个java

//  $push  // 可以一次添加多个值,但是可以重复
db.users.updateMany({name:"dafei"},{$push:{hobby:"java"}})
db.users.updateMany(
	{name:"dafei"},
	{$push:{hobby:{$each:["java","c","c++"]}}}	
)       

// $addToset  不会重复
db.users.updateMany(
	{name:"dafei"},
	{
		$addToSet:{hobby:"go"}
	}
)
//不可取   //会将 ["go","c"] 作为一个值提交
db.users.updateMany(
	{name:"dafei"},
	{
		$addToSet:{hobby:["go","c"]}  
	}
)


3.6.2 删除
//删除   $pop   $pull
//删除最后一个    1--最后一个  -1--第一个

// $pop      局限: 只能从头或者从尾删除, 不能通过指定元素删除
	db.users.updateMany(
	{name:"dafei"},
	{
		$pop:{hobby:-1}
	}
)
db.users.updateMany(
	{name:"dafei"},
	{
		$pop:{hobby:1}
	}
)

//$pull  删除数组中数据, 通过指定内容删除
//按内容删除
db.users.updateMany(
	{name:"dafei"},
	{
		$pull:{hobby:"java"}
	}
)


3.6.3 修改
//改值    $set:{"hobby.1":"java"}      $set:{"hobby.$":"c"}
//通过索引修改
db.users.updateMany(
	{name:"dafei"},
	{
		$set:{"hobby.1":"java"}
	}
)

//通过内容
db.users.updateMany(
	{name:"dafei",hobby:"go"},
	{
		$set:{"hobby.$":"c"}
	}
)


3.6.4 查询
//查询
db.users.find({
	name:"dafei"
})



4.聚合操作

聚合框架
什么是Mongodb聚合框架
MongoDB聚合框架(Aggregation Framewordk) 是一个计算框架,他可以作用在一个或集合集合中对集合中的数据进行一系列运算,将这些数据转化为期望的形式
从效果而言, 聚合框架相当于SQL查询中
Group by  left join
管道(Pipeline)步骤(Stage)

整个聚合运算工程称之为管道, 它是由多个步骤组成
每个管道:
  1:接收一系列文档(原始数据)
  2:每一个步骤对这些文档进行一系列运算
  3:结果文档输出给下一个步骤

基本语法:
pipeline = [$stage1, $stage2, .... $stageN]

db.集合.aggregate(
     pipeline,
     {
           options
     }
)

eg:
db.user.aggregate(
      [
           {
                $group:{
                       _id:"$name",
                       namecount:{$sum:1}
                 }
            }
        ]
);
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$geoNear:输出接近某一地理位置的有序文档。



4.文档设计



4.1三 泛式

解释: 
1NF:原子性 字段不可再分,否则就不是关系数据库; ------------字段不可分; 
2NF:唯一性 要求数据库表中的每个实例或行必须可以被惟一的区分; -----有主键,非主键字段依赖主键,不能部分依赖;
3NF:每列都与主键有直接关系,不存在传递依赖; -------非主键字段不能相互依赖; 
关系数据库:
开发中设计表需要满足第三方式即可,但是,实际开发很多
时候使用打破第三范式操作

真实开发设计:针对频繁查询表,使用冗余字段方式(打破第三范式)
优点:查询很快缺点: DML操作麻烦



4.2 反泛式

使用冗余字段方式替换关联映射
使用数组方式替换一对多
mongodb 文档关系设计
一对一  冗余字段
qq{
 id,num,url
}

多对一   缺陷:没有部门列表/查询操作  员工与部门独立,采用冗余字段方式处理
		
		employee{                  employee {         dept{
		  id,name,                     id,name,          id,name,
		  dept:{                       deptName        }
		    id,name                    deptId
		  }                         }
		}

一对多 (不能有太多)                            (可以很多)
dept{              employee{                    dept{              employee{ 
	id,name           id,name                     id,name            id,name
	esList:{       }                              esList:{         }
	{id,name},                                     employee_id,
	{id,name}...                                   employee_id...
	}                                           }

}

多对多 (同一对多)



5.集成springboot



5.1依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent> 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>    

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--spring boot data mongodb-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
</dependencies>



5.2配置

# application.properties

# 配置数据库连接

#格式: mongodb://账号:密码@ip:端口/数据库?认证数据库

#spring.data.mongodb.uri=mongodb://root:admin@localhost/mongodemo?authSource=admin

spring.data.mongodb.uri=mongodb://localhost/mongodemo

# 配置MongoTemplate的执行日志

logging.level.org.springframework.data.mongodb.core=debug



5.3后端

1.domain  贴 @Document("users") //设置文档所在的集合
2.domain private ObjectId _id;字段 贴@Id //文档的id使用ObjectId类型来封装,并且贴上@Id注解
3.写service 及 impl 
4.写UserRepository 继承 MongoRepository<User,String>
   /**
 	* 1.定义一个接口
 	* 2.继承MongoRepository
 	* 3.指定2个泛型 泛型1:该接口操作实体  泛型2:实体的主键类型
 	* 4.贴一个@Repository  可以不贴
 	*/
5.写crud测试 
	增 service.save(user);
	改   //先查询   //再替换  //再更新
		User user = service.get("5edb3dea770c456b8fda2888");
		user.setName("lisi");
		service.save(user);
	删        service.delete("5ed9eacac01b0000d600027c");
    查一个    service.get("5ed9eacac01b0000d600027c")
	查所有    service.selectAll()



5.4 Jpa规范

方法名要求:前缀 + 实体类属性名(表的列名)
	前缀: findBy      queryBy

· Spring Data方法命名规范

|      关键字      |                    例子                    |              JPQL               |
| :--------------: | :----------------------------------------: | :-----------------------------: |
|       And        | findByNameAndAge(String name, Integer age) |   where name = ? and age = ?    |
|        Or        | findByNameOrAge(String name, Integer age)  |    where name = ? or age = ?    |
|        Is        |          findByName(String name)           |         where name = ?          |
|     Between      | findByAgeBetween(Integer min, Integer max) |    where age between ? and ?    |
|     LessThan     |       findByAgeLessThan(Integer age)       |          where age < ?          |
|  LessThanEqual   |    findByAgeLessThanEqual(Integer age)     |         where age <= ?          |
|   GreaterThan    |     findByAgeGreaterThan(Integer age)      |          where age > ?          |
| GreaterThanEqual |   findByAgeGreaterThanEqual(Integer age)   |         where age >= ?          |
|      After       |             等同于GreaterThan              |                                 |
|      Before      |               等同于LessThan               |                                 |
|      IsNull      |             findByNameIsNull()             |       where name is null        |
|    IsNotNull     |           findByNameIsNotNull()            |     where name is not null      |
|       Like       |        findByNameLike(String name)         |        where name like ?        |
|     NotLike      |       findByNameNotLike(String name)       |      where name not like ?      |
|   StartingWith   |    findByNameStartingWith(String name)     |      where name like '?%'       |
|    EndingWith    |     findByNameEndingWith(String name)      |      where name like '%?'       |
|    Containing    |     findByNameContaining(String name)      |      where name like '%?%'      |
| OrderByXx[desc]  |     findByIdOrderByXx[Desc] (Long id)      | where id = ? order by Xx [desc] |
|       Not        |         findByNameNot(String name)         |         where name != ?         |
|        In        |        findByIdIn(List\<Long\> ids)        |       where id in ( ... )       |
|      NotIn       |      findByIdNotIn(List\<Long\> ids)       |     where id not in ( ... )     |
|       True       |               findByXxTrue()               |         where Xx = true         |
|      False       |              findByXxFalse()               |        where Xx = false         |
|    IgnoreCase    |     findByNameIgnoreCase(String name)      |   where name = ? (忽略大小写)   |



5.5 分页查询

	@Autowired
    private MongoTemplate mongoTemplate;

// 创建查询对象 (核心) (拼接Mql语句)
        Query query = new Query();

        /*//第一种分页
        // 设置分页信息
        query.skip(3).limit(3);
        // 设置排序规则
        query.with(Sort.by(Sort.Direction.ASC,"id"));*/


        //第二种分页
        //  (  当前页(0开始), 每页显示数  ,排序规则  ,排序字段  )
        Pageable of = PageRequest.of(1, 3, Sort.Direction.ASC, "id");
        query.with(of);

        List<User> list = mongoTemplate.find(query, User.class, "users");
        list.forEach(System.err::println);



5.6条件

普通条件		
		// 构建限制条件 {"name": "dafei"}
        Criteria criteria = Criteria.where("name").is("dafei");
        // 创建查询对象
        Query query = new Query();
        // 添加限制条件
        query.addCriteria(criteria);
        List<User> list = mongoTemplate.find(query, User.class, "users");
        list.forEach(System.err::println);


or:
    Criteria criteria = new Criteria().orOperator(
                Criteria.where("name").is("dafei"),
                Criteria.where("age").lt(30)
        );

and:
    Criteria criteria = new Criteria().andOperator(
                Criteria.where("name").regex(".*fei.*"),
                Criteria.where("age").gte(30).lte(32)
        );



版权声明:本文为qq_45627063原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。