【探花交友】day03—MongoDB基础
目录
课程介绍
1、通用设置
1.1 需求分析
1.2 查询通用设置
1.2 陌生人问题
1.3 通知设置
1.4 黑名单管理
2、MongoDB简介
1.1、MongoDB简介
1.2、MongoDB的特点
1.3 数据类型
3、MongoDB入门
2.1、数据库以及表的操作
2.2、新增数据
2.3、更新数据
2.4、删除数据
2.5、查询数据
2.6、索引
2.7、执行计划
4、SpringData-Mongo
4.1、环境搭建
4.2、完成基本操作
5、今日佳人
5.1、表结构设计
5.2、服务提供者
5.3、代码实现
课程介绍
-
MongoDB环境搭建
-
MongoDB基本CRUD操作
-
通过JavaApi操作MongoDB
-
SpringBoot整合MongoDB
1、通用设置
1.1 需求分析
1.1.1 需求分析
通用设置,包含探花交友APP基本的软件设置功能。包含:
设置陌生人问题:当平台其他用户想进行在线交流时需要回答陌生人问题。
通用设置:包含一些APP通知设置
黑名单:对于不感兴趣的用户设置黑名单屏蔽骚扰


1.1.2 数据库表
通用设置
CREATE TABLE `tb_settings` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) DEFAULT NULL,`like_notification` tinyint(4) DEFAULT '1' COMMENT '推送喜欢通知',`pinglun_notification` tinyint(4) DEFAULT '1' COMMENT '推送评论通知',`gonggao_notification` tinyint(4) DEFAULT '1' COMMENT '推送公告通知',`created` datetime DEFAULT NULL,`updated` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='设置表';
问题表
CREATE TABLE `tb_question` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) DEFAULT NULL COMMENT '用户id',`txt` varchar(200) DEFAULT NULL COMMENT '问题内容',`created` datetime DEFAULT NULL,`updated` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
黑名单
CREATE TABLE `tb_black_list` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) DEFAULT NULL,`black_user_id` bigint(20) DEFAULT NULL,`created` datetime DEFAULT NULL,`updated` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='黑名单';
1.1.3 搭建提供者环境
实体类
(1) Settings
CREATE TABLE `tb_black_list` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) DEFAULT NULL,`black_user_id` bigint(20) DEFAULT NULL,`created` datetime DEFAULT NULL,`updated` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='黑名单';
(2)Question
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Question extends BasePojo {private Long id;private Long userId;//问题内容private String txt;}
(3)BlackList
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BlackList extends BasePojo {private Long id;private Long userId;private Long blackUserId;
}
mapper接口
(1)SettingsMapper
public interface SettingsMapper extends BaseMapper<Settings> {
}
(2)QuestionMapper
public interface QuestionMapper extends BaseMapper<Question> {}
(3)BlackListMapper
public interface BlackListMapper extends BaseMapper<BlackList> {}
api接口
(1) SettingApi
package com.tanhua.dubbo.api;import com.tanhua.domain.db.Settings;public interface SettingsApi {}
(2)QuestionApi
package com.tanhua.dubbo.api;import com.tanhua.domain.db.Question;public interface QuestionApi {}
(3)BlackListApi
package com.tanhua.dubbo.api;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.tanhua.domain.db.UserInfo;public interface BlackListApi {}
api服务实现类
(1)SettingServiceImpl
package com.tanhua.dubbo.api;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.domain.db.Settings;
import com.tanhua.dubbo.mapper.SettingsMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;@DubboService
public class SettingsApiImpl implements SettingsApi {@Autowiredprivate SettingsMapper settingsMapper;}
(2)QuestionServiceImpl
package com.tanhua.dubbo.api;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.domain.db.Question;
import com.tanhua.dubbo.mapper.QuestionMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;@DubboService
public class QuestionApiImpl implements QuestionApi {@Autowiredprivate QuestionMapper questionMapper;}
(3)BlackListServiceImpl
package com.tanhua.dubbo.api;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tanhua.domain.db.BlackList;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.dubbo.mapper.BlackListMapper;
import com.tanhua.dubbo.mapper.UserInfoMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;@DubboService
public class BlackListApiImpl implements BlackListApi {@Autowiredprivate BlackListMapper blackListMapper;
}
1.2 查询通用设置
1.2.1 接口文档

1.2.2 代码实现
vo对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SettingsVo implements Serializable {private Long id;private String strangerQuestion = "";private String phone;private Boolean likeNotification = true;private Boolean pinglunNotification = true;private Boolean gonggaoNotification = true;}
SettingsController
在tanhua-server工程创建SettingsController完成代码编写
@RestController
@RequestMapping("/users")
public class SettingsController {@Autowiredprivate SettingsService settingsService;/*** 查询通用设置*/@GetMapping("/settings")public ResponseEntity settings() {SettingsVo vo = settingsService.settings();return ResponseEntity.ok(vo);}
}
SettingService
在tanhua-server工程创建SettingService完成代码编写
@Service
public class SettingsService {@DubboReferenceprivate QuestionApi questionApi;@DubboReferenceprivate SettingsApi settingsApi;@DubboReferenceprivate BlackListApi blackListApi;//查询通用设置public SettingsVo settings() {SettingsVo vo = new SettingsVo();//1、获取用户idLong userId = UserHolder.getUserId();vo.setId(userId);//2、获取用户的手机号码vo.setPhone(UserHolder.getMobile());//3、获取用户的陌生人问题Question question = questionApi.findByUserId(userId);String txt = question == null ? "你喜欢java吗?" : question.getTxt();vo.setStrangerQuestion(txt);//4、获取用户的APP通知开关数据Settings settings = settingsApi.findByUserId(userId);if(settings != null) {vo.setGonggaoNotification(settings.getGonggaoNotification());vo.setPinglunNotification(settings.getPinglunNotification());vo.setLikeNotification(settings.getLikeNotification());}return vo;}
}
QuestionApi
在tanhua-dubbo中的QuestionApi和QuestionApiImpl补充方法
@Override
public Question findByUserId(Long userId) {QueryWrapper<Question> qw = new QueryWrapper<>();qw.eq("user_id",userId);return questionMapper.selectOne(qw);
}
SettingApi
在tanhua-dubbo中的SettingApi和SettingApiImpl补充方法
//根据用户id查询
public Settings findByUserId(Long userId) {QueryWrapper<Settings> qw = new QueryWrapper<>();qw.eq("user_id",userId);return settingsMapper.selectOne(qw);
}
1.2 陌生人问题
对数据库表进行操作:如果存在数据,更新数据库。如果不存在数据,保存数据库表数据
1.2.1 接口文档

1.2.2 代码实现
SettingsController
/*** 设置陌生人问题*/
@PostMapping("/questions")
public ResponseEntity questions(@RequestBody Map map) {//获取参数String content = (String) map.get("content");settingsService.saveQuestion(content);return ResponseEntity.ok(null);
}
SettingsService
//设置陌生人问题
public void saveQuestion(String content) {//1、获取当前用户idLong userId = UserHolder.getUserId();//2、调用api查询当前用户的陌生人问题Question question = questionApi.findByUserId(userId);//3、判断问题是否存在if(question == null) {//3.1 如果不存在,保存question = new Question();question.setUserId(userId);question.setTxt(content);questionApi.save(question);}else {//3.2 如果存在,更新question.setTxt(content);questionApi.update(question);}
}
QuestionApi
tanhua-dubbo工程中的QuestionApi和QuestionApiImpl中添加保存和更新方法
@Override
public void save(Question question) {questionMapper.insert(question);
}@Override
public void update(Question question) {questionMapper.updateById(question);
}
1.3 通知设置
1.3.1 接口文档
通知管理:对通知进行保存或者更新的操作
http://192.168.136.160:3000/project/19/interface/api/280

1.3.2 代码实现
SettingsController
/*** 通知设置*/
@PostMapping("/notifications/setting")
public ResponseEntity notifications(@RequestBody Map map) {//获取参数settingsService.saveSettings(map);return ResponseEntity.ok(null);
}
SettingsService
//通知设置
public void saveSettings(Map map) {boolean likeNotification = (Boolean) map.get("likeNotification");boolean pinglunNotification = (Boolean) map.get("pinglunNotification");boolean gonggaoNotification = (Boolean) map.get("gonggaoNotification");//1、获取当前用户idLong userId = UserHolder.getUserId();//2、根据用户id,查询用户的通知设置Settings settings = settingsApi.findByUserId(userId);//3、判断if(settings == null) {//保存settings = new Settings();settings.setUserId(userId);settings.setPinglunNotification(pinglunNotification);settings.setLikeNotification(likeNotification);settings.setGonggaoNotification(gonggaoNotification);settingsApi.save(settings);}else {settings.setPinglunNotification(pinglunNotification);settings.setLikeNotification(likeNotification);settings.setGonggaoNotification(gonggaoNotification);settingsApi.update(settings);}
}
SettingsApi
tanhua-dubbo工程中的SettingsApi和SettingsApiImpl中添加保存和更新方法
@Override
public void save(Settings settings) {settingsMapper.insert(settings);
}@Override
public void update(Settings settings) {settingsMapper.updateById(settings);
}
1.4 黑名单管理
1.3.1 接口文档
-
查询黑名单列表


-
移除黑名单

1.3.2 分页查询
vo对象
tanhua-domain工程的配置分页vo对象
package com.tanhua.domain.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.Collections;
import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {private Integer counts = 0;//总记录数private Integer pagesize;//页大小private Integer pages = 0;//总页数private Integer page;//当前页码private List<?> items = Collections.emptyList(); //列表public PageResult(Integer page,Integer pagesize,int counts,List list) {this.page = page;this.pagesize = pagesize;this.items = list;this.counts = counts;this.pages = counts % pagesize == 0 ? counts / pagesize : counts / pagesize + 1;}}
SettingsController
/*** 分页查询黑名单列表*/
@GetMapping("/blacklist")
public ResponseEntity blacklist(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size) {//1、调用service查询PageResult pr = settingsService.blacklist(page,size);//2、构造返回return ResponseEntity.ok(pr);
}/*** 取消黑名单*/
@DeleteMapping("/blacklist/{uid}")
public ResponseEntity deleteBlackList(@PathVariable("uid") Long blackUserId) {settingsService.deleteBlackList(blackUserId);return ResponseEntity.ok(null);
}
SettingService
//分页查询黑名单列表
public PageResult blacklist(int page, int size) {//1、获取当前用户的idLong userId = UserHolder.getUserId();//2、调用API查询用户的黑名单分页列表 Ipage对象IPage<UserInfo> iPage = blackListApi.findByUserId(userId,page,size);//3、对象转化,将查询的Ipage对象的内容封装到PageResult中PageResult pr = new PageResult(page,size,iPage.getTotal(),iPage.getRecords());//4、返回return pr;
}//取消黑名单
public void deleteBlackList(Long blackUserId) {//1、获取当前用户idLong userId = UserHolder.getUserId();//2、调用api删除blackListApi.delete(userId,blackUserId);
}
BlackListApi
@Override
public IPage<UserInfo> findByUserId(Long userId, int page, int size) {//1、构建分页参数对象PagePage pages = new Page(page,size);//2、调用方法分页(自定义编写 分页参数Page,sql条件参数)return userInfoMapper.findBlackList(pages,userId);
}@Override
public void delete(Long userId, Long blackUserId) {QueryWrapper<BlackList> qw = new QueryWrapper<>();qw.eq("user_id",userId);qw.eq("black_user_id",blackUserId);blackListMapper.delete(qw);
}
UserInfoMapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {@Select("select * from tb_user_info where id in (\n" +" SELECT black_user_id FROM tb_black_list where user_id=#{userId}\n" +")")IPage<UserInfo> findBlackList(@Param("pages") Page pages, @Param("userId") Long userId);
}
MybatisPlusConfig
tanhua-dubbo-db引导类开启mybatis-plus分页插件支持
public interface UserInfoMapper extends BaseMapper<UserInfo> {@Select("select * from tb_user_info where id in (\n" +" SELECT black_user_id FROM tb_black_list where user_id=#{userId}\n" +")")IPage<UserInfo> findBlackList(@Param("pages") Page pages, @Param("userId") Long userId);
}
使用mybatis-plus的分页:
-
创建分页对象:Page,指定当前页和每页查询条数
-
基础查询:mapper.selectPage(page,查询条件)
-
自定义查询:Ipage 方法名称(Page对象,xxx查询条件)
2、MongoDB简介
对于社交类软件的功能,我们需要对它的功能特点做分析:
-
数据量会随着用户数增大而增大
-
读多写少
-
价值较低
-
非好友看不到其动态内容
-
地理位置的查询
-
……
针对以上特点,我们来分析一下:
-
mysql:关系型数据库(效率低)
-
redis:redis缓存(微博,效率高,数据格式不丰富)
-
对于数据量大而言,显然不能够使用关系型数据库进行存储,我们需要通过MongoDB进行存储
-
对于读多写少的应用,需要减少读取的成本
-
比如说,一条SQL语句,单张表查询一定比多张表查询要快
-
探花交友
-
mongodb:存储业务数据(圈子,推荐的数据,小视频数据,点赞,评论等)
-
redis:承担的角色是缓存层(提升查询效率)
-
mysql:存储和核心业务数据,账户
1.1、MongoDB简介
MongoDB:是一个高效的非关系型数据库(不支持表关系:只能操作单表)

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
官网:MongoDB: The Developer Data Platform | MongoDB
1.2、MongoDB的特点
MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库。具体特点总结如下:
-
面向集合存储,易于存储对象类型的数据
-
模式自由
-
支持动态查询
-
支持完全索引,包含内部对象
-
支持复制和故障恢复
-
使用高效的二进制数据存储,包括大型对象(如视频等)
-
自动处理碎片,以支持云计算层次的扩展性
-
支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl及C++语言的驱动程 序, 社区中也提供了对Erlang及.NET 等平台的驱动程序
-
文件存储格式为 BSON(一种 JSON 的扩展)
1.2.1、通过docker安装MongoDB
在课程资料的虚拟机中已经提供了MongoDB的镜像和容器,我们只需要使用简单的命令即可启动
#进入base目录 cd /root/docker-file/base/ #批量创建启动容器,其中已经包含了redis,zookeeper,mongodb容器 docker-compose up -d #查看容器 docker ps -a

可以看到mongoDB已经启动,对外暴露了27017的操作端口
1.2.2、MongoDB体系结构
MongoDB 的逻辑结构是一种层次结构。主要由: 文档(document)、集合(collection)、数据库(database)这三部分组成的。逻辑结构是面 向用户的,用户使用 MongoDB 开发应用程序使用的就是逻辑结构。
-
MongoDB 的文档(document),相当于关系数据库中的一行记录。
-
多个文档组成一个集合(collection),相当于关系数据库的表。
-
多个集合(collection),逻辑上组织在一起,就是数据库(database)。
-
一个 MongoDB 实例支持多个数据库(database)。 文档(document)、集合(collection)、数据库(database)的层次结构如下图:

为了更好的理解,下面与SQL中的概念进行对比:
| SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
|---|---|---|
| database | database | 数据库 |
| table | collection | 数据库表/集合 |
| row | document | 表中的一条数据 |
| column | field | 数据字段/域 |
| index | index | 索引 |
| table joins | 表连接,MongoDB不支持 | |
| primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |

1.3 数据类型
-
数据格式:BSON {aa:bb}
-
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-字符保存到数据库中,二进制数据是唯一的方式。
3、MongoDB入门
2.1、数据库以及表的操作
#查看所有的数据库
> show dbs#通过use关键字切换数据库
> use admin#创建数据库
#说明:在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库
> use testdb> show dbs #并没有创建数据库> db.user.insert({id:1,name:'zhangsan'}) #插入数据> show dbs#查看表
> show tables> show collections#删除集合(表)
> db.user.drop()
true #如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。#删除数据库
> use testdb #先切换到要删除的数据中> db.dropDatabase() #删除数据库
2.2、新增数据
在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)。
#插入数据
#语法:db.表名.insert(json字符串)> db.user.insert({id:1,username:'zhangsan',age:20})> db.user.find() #查询数据
2.3、更新数据
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update(<query>,<update>,[upsert: <boolean>,multi: <boolean>,writeConcern: <document>]
)
参数说明:
-
query : update的查询条件,类似sql update查询内where后面的。
-
update : update的对象和一些更新的操作符(如$,$inc.$set)等,也可以理解为sql update查询内set后面的
-
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
-
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
-
writeConcern :可选,抛出异常的级别。
#查询全部
> db.user.find()#更新数据
> db.user.update({id:1},{$set:{age:22}}) #注意:如果这样写,会删除掉其他的字段
> db.user.update({id:1},{age:25})#更新不存在的字段,会新增字段
> db.user.update({id:2},{$set:{sex:1}}) #更新数据#更新不存在的数据,默认不会新增数据
> db.user.update({id:3},{$set:{sex:1}})#如果设置第一个参数为true,就是新增数据
> db.user.update({id:3},{$set:{sex:1}},true)
2.4、删除数据
通过remove()方法进行删除数据,语法如下:
db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <document>}
)
参数说明:
-
query :(可选)删除的文档的条件。
-
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
-
writeConcern :(可选)抛出异常的级别。
实例:
#删除数据
> db.user.remove({})#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})> db.user.remove({age:22},true)#删除所有数据
> db.user.remove({})
2.5、查询数据
MongoDB 查询数据的语法格式如下:
db.user.find([query],[fields])
-
query :可选,使用查询操作符指定查询条件
-
fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
条件查询:
| 操作 | 格式 | 范例 | RDBMS中的类似语句 |
|---|---|---|---|
| 等于 | {<key>:<value>} | db.col.find({"by":"黑马程序员"}).pretty() | where by = '黑马程序员' |
| 小于 | {<key>:{$lt:<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
| 小于或等于 | {<key>:{$lte:<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
| 大于 | {<key>:{$gt:<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
| 大于或等于 | {<key>:{$gte:<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
| 不等于 | {<key>:{$ne:<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
实例:
#插入测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})db.user.find() #查询全部数据
db.user.find({},{id:1,username:1}) #只查询id与username字段
db.user.find().count() #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2#分页查询:Skip()跳过几条,limit()查询条数
db.user.find().limit(2).skip(1) #跳过1条数据,查询2条数据
db.user.find().sort({id:-1}) #按照id倒序排序,-1为倒序,1为正序
2.6、索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
#创建索引
> db.user.createIndex({'age':1})#查看索引
> db.user.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "testdb.user"}
]
#说明:1表示升序创建索引,-1表示降序创建索引。
2.7、执行计划
MongoDB 查询分析可以确保我们建议的索引是否有效,是查询语句性能分析的重要工具。
#插入1000条数据
for(var i=1;i<1000;i++)db.user.insert({id:100+i,username:'name_'+i,age:10+i})#查看执行计划
> db.user.find({age:{$gt:100},id:{$lt:200}}).explain()#测试没有使用索引
> db.user.find({username:'zhangsan'}).explain()#winningPlan:最佳执行计划
#"stage" : "FETCH", #查询方式,常见的有COLLSCAN/全表扫描、IXSCAN/索引扫描、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询
4、SpringData-Mongo
Spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作,封装了底层的mongodb-driver。
地址:Spring Data MongoDB
使用Spring-Data-MongoDB很简单,只需要如下几步即可:
-
导入起步依赖
-
编写配置信息
-
编写实体类(配置注解 @Document,@Id)
-
操作mongodb
-
注入MongoTemplate对象,完成CRUD操作
-
编写Repository接口,注入接口完成基本Crud操作
-
4.1、环境搭建
第一步,导入依赖:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
第二步,编写application.yml配置文件
spring:data:mongodb:uri: mongodb://192.168.136.160:27017/test
第三步,编写启动类
package com.tanhua.mongo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MongoApplication {public static void main(String[] args) {SpringApplication.run(MongoApplication.class, args);}
}
4.2、完成基本操作
第一步,编写实体类
package com.tanhua.mongo.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(value="person")
public class Person {private ObjectId id;private String name;private int age;private String address;}
第二步,通过MongoTemplate完成CRUD操作
package cn.itcast.mongo.test;import cn.itcast.mongo.MongoApplication;
import cn.itcast.mongo.domain.Person;
import org.bson.types.ObjectId;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest(classes = MongoApplication.class)
public class MongoTest {/*** SpringData-mongodb操作* 1、配置实体类* 2、实体类上配置注解(配置集合和对象间的映射关系)* 3、注入MongoTemplate对象* 4、调用对象方法,完成数据库操作*/@Autowiredprivate MongoTemplate mongoTemplate;//保存@Testpublic void testSave() {for (int i = 0; i < 10; i++) {Person person = new Person();person.setId(ObjectId.get()); //ObjectId.get():获取一个唯一主键字符串person.setName("张三"+i);person.setAddress("北京顺义"+i);person.setAge(18+i);mongoTemplate.save(person);}}//查询-查询所有@Testpublic void testFindAll() {List<Person> list = mongoTemplate.findAll(Person.class);for (Person person : list) {System.out.println(person);}}@Testpublic void testFind() {//查询年龄小于20的所有人Query query = new Query(Criteria.where("age").lt(20)); //查询条件对象//查询List<Person> list = mongoTemplate.find(query, Person.class);for (Person person : list) {System.out.println(person);}}/*** 分页查询*/@Testpublic void testPage() {Criteria criteria = Criteria.where("age").lt(30);//1、查询总数Query queryCount = new Query(criteria);long count = mongoTemplate.count(queryCount, Person.class);System.out.println(count);//2、查询当前页的数据列表, 查询第二页,每页查询2条Query queryLimit = new Query(criteria).limit(2)//设置每页查询条数.skip(2) ; //开启查询的条数 (page-1)*sizeList<Person> list = mongoTemplate.find(queryLimit, Person.class);for (Person person : list) {System.out.println(person);}}/*** 更新:* 根据id,更新年龄*/@Testpublic void testUpdate() {//1、条件Query query = Query.query(Criteria.where("id").is("5fe404c26a787e3b50d8d5ad"));//2、更新的数据Update update = new Update();update.set("age", 20);mongoTemplate.updateFirst(query, update, Person.class);}@Testpublic void testRemove() {Query query = Query.query(Criteria.where("id").is("5fe404c26a787e3b50d8d5ad"));mongoTemplate.remove(query, Person.class);}
}
5、今日佳人
在用户登录成功后,就会进入首页,首页中有今日佳人、推荐好友、探花、搜附近等功能。
今日佳人,会推荐缘分值最大的用户,进行展现出来。缘分值的计算是由用户的行为进行打分,如:点击、点赞、评论、学历、婚姻状态等信息组合而成的。
实现:我们先不考虑推荐的逻辑,假设现在已经有推荐的结果,我们只需要从结果中查询到缘分值最高的用户就可以了。至于推荐的逻辑以及实现,我们将后面的课程中讲解。
流程:

5.1、表结构设计
#表结构 recommend_user
{"userId":1001, #推荐的用户id"toUserId":1002, #用户id"score":90, #推荐得分"date":"2019/1/1" #日期
}
在MongoDB中只存储用户的id数据,其他的数据需要通过接口查询。
5.2、服务提供者
5.2.0、导入依赖
找到tanhua-domain模块的pom.xml打开mongo的依赖

5.2.1、实体类
@AllArgsConstructor
@NoArgsConstructor
@Data
@Document(collection = "recommend_user")
public class RecommendUser implements java.io.Serializable {private ObjectId id; //主键idprivate Long userId; //推荐的用户idprivate Long toUserId; //用户idprivate Double score =0d; //推荐得分private String date; //日期
}
5.2.2、RecommendUserApi接口
public interface RecommendUserApi {RecommendUser queryWithMaxScore(Long toUserId);
}
5.2.3、RecommendUserApiImpl
@DubboService
public class RecommendUserApiImpl implements RecommendUserApi {@Autowiredprivate MongoTemplate mongoTemplate;//查询今日佳人public RecommendUser queryWithMaxScore(Long toUserId) {//根据toUserId查询,根据评分score排序,获取第一条//构建CriteriaCriteria criteria = Criteria.where("toUserId").is(toUserId);//构建Query对象Query query = Query.query(criteria).with(Sort.by(Sort.Order.desc("score"))).limit(1);//调用mongoTemplate查询return mongoTemplate.findOne(query,RecommendUser.class);}
}
5.2.4、application配置
server:port: 18082
spring:application:name: tanhua-dubbo-mongocloud:nacos:discovery:server-addr: 192.168.136.160:8848data:mongodb:uri: mongodb://192.168.136.160:27017/tanhua
dubbo:protocol:name: dubboport: 20882registry:address: spring-cloud://localhostscan:base-packages: com.tanhua.dubbo.api #dubbo中包扫描
5.2.5 启动类
package com.tanhua.dubbo;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class DubboMongoApplication {public static void main(String[] args) {SpringApplication.run(DubboMongoApplication.class,args);}
}
5.3、代码实现
5.3.1、接口说明
地址:http://192.168.136.160:3000/project/19/interface/api/100


5.3.2、TanhuaController
@RestController
@RequestMapping("/tanhua")
public class TanhuaController {@Autowiredprivate TanhuaService tanhuaService;//今日佳人@GetMapping("/todayBest")public ResponseEntity todayBest() {TodayBest vo = tanhuaService.todayBest();return ResponseEntity.ok(vo);}
}
5.3.3、TanhuaService
@Service
public class TanhuaService {@DubboReferenceprivate RecommendUserApi recommendUserApi;@DubboReferenceprivate UserInfoApi userInfoApi;@DubboReferenceprivate QuestionApi questionApi;@Autowiredprivate HuanXinTemplate template;//查询今日佳人数据public TodayBest todayBest() {//1、获取用户idLong userId = UserHolder.getUserId();//2、调用API查询RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);if(recommendUser == null) {recommendUser = new RecommendUser();recommendUser.setUserId(1l);recommendUser.setScore(99d);}//3、将RecommendUser转化为TodayBest对象UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());TodayBest vo = TodayBest.init(userInfo, recommendUser);//4、返回return vo;}
}
5.3.4、vo对象
package com.tanhua.domain.vo;import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.RecommendUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;/*** 今日佳人*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TodayBest {private Long id; //用户idprivate String avatar;private String nickname;private String gender; //性别 man womanprivate Integer age;private String[] tags;private Long fateValue; //缘分值/*** 在vo对象中,补充一个工具方法,封装转化过程*/public static TodayBest init(UserInfo userInfo, RecommendUser recommendUser) {TodayBest vo = new TodayBest();BeanUtils.copyProperties(userInfo,vo);if(userInfo.getTags() != null) {vo.setTags(userInfo.getTags().split(","));}vo.setFateValue(recommendUser.getScore().longValue());return vo;}
}
5.3.5、解决MongoDB启动bug
在项目中,添加了mongo的依赖的话,springboot就会自动去连接本地的mongo,由于他连接不上会导致出错。
解决有2种方案:
-
排除掉mongo的依赖
-
springboot中添加排除自动配置的注解
package com.tanhua.server;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;@SpringBootApplication(exclude = {MongoAutoConfiguration.class,MongoDataAutoConfiguration.class }) //排除mongo的自动配置 public class TanhuaServerApplication {public static void main(String[] args) {SpringApplication.run(TanhuaServerApplication.class,args);} }
相关文章:
【探花交友】day03—MongoDB基础
目录 课程介绍 1、通用设置 1.1 需求分析 1.2 查询通用设置 1.2 陌生人问题 1.3 通知设置 1.4 黑名单管理 2、MongoDB简介 1.1、MongoDB简介 1.2、MongoDB的特点 1.3 数据类型 3、MongoDB入门 2.1、数据库以及表的操作 2.2、新增数据 2.3、更新数据 2.4、删除数…...
【Vue教程】使用Vite快速搭建前端工程化项目 | Vue3 | Vite | Node.js
🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 🚩今天毛毛张分享的是关于如何快速🏃♂️搭建一个前端工程化的项目的环境搭建以及流程🌠 文章目录 1.前端工程化环境搭建&#…...
手机租赁平台开发全攻略打造高效便捷的租赁服务系统
内容概要 手机租赁平台开发,简单说就是让用户能轻松租赁各类手机的高效系统。这一平台不仅帮助那些想要临时使用高端手机的人们节省了不少资金,还为商家开辟了新的收入渠道。随着智能手机的普及,很多人并不需要长期拥有一部手机,…...
自由学习记录(31)
Java连接MySQL 找到那个关键jar包然后导入选中,就配置好MySQL的JDBC(Java Database Connectivity)了 菜单--文件--项目结构 项目设置--模块--选择要附着的项目--选择依赖--选中模块源--选中加号添加jar包 解压之后在里面可以看到这个最关键…...
【探花交友】用户登录总结
1.发送验证码 1.发送post请求 数据封装在map 获取map的手机号码 2.调用service层将手机号码 传入过去 3.正常返回状态码200 RestController RequestMapping("/user") public class LoginController {Autowiredprivate UserService userService;/*** 获取登录验证码*…...
LabVIEW声波谐振管自动化测量系统
开发了一种基于LabVIEW的声波谐振管自动化测量系统。该系统利用LabVIEW的强大功能,实现了对声波谐振频率的精确测量,提高了实验数据的采集效率和准确性。系统主要应用于物理教学和科研中,用于研究声波在谐振管中的传播特性。 项目背景 传统的…...
elasticsearch中的倒排索引
倒排索引是搜索引擎中常用的一种数据结构,适用于全文检索,能够通过文本内容高效检索到相应的文档。 一、倒排索引的基本概念 正排索引:传统的索引方式,按照文档id顺序存储文档,通过文档id找到文档对应的词。因此当需…...
【Elasticsearch】DSL查询文档
目录 1.DSL查询文档 1.1.DSL查询分类 1.2.全文检索查询 1.2.1.使用场景 1.2.2.基本语法 1.2.3.示例 1.2.4.总结 1.3.精准查询 1.3.1.term查询 1.3.2.range查询 1.3.3.总结 1.4.地理坐标查询 1.4.1.矩形范围查询 1.4.2.附近查询 1.5.复合查询 1.5.1.相关性算分 …...
接口测试Day04-postman生成测试报告ihrm项目
测试报告-利用newman插件 安装node.js 安装 双击 .msi 文件,一路下一步安装即可。无需特殊设定。测试安装成功 npm -v 安装npm 安装newman 安装newman npm install -g newman试安装成功 newman -v安装newman插件 - 扩展版 npm install -g newman-reporter-htmlex…...
常见的排序算法过程和比较分析
比较分析 排序类别排序算法时间复杂度(最好)时间复杂度(最坏)时间复杂度(平均)辅助空间复杂度稳定性插入排序直接插入排序O(n)O(n)O(n)O(1)稳定插入排序折半插入排序O(n)O(n)O(n)O(1)稳定插入排序希尔排序…...
基于Vue+SSM+SpringCloudAlibaba书籍管理系统
功能要求 一、登录功能(http://localhost:8080/#/login) 输入账号和密码(admin/admin)进行登录: 如果密码错误,给出提示信息 如果密码正确,跳转到主页 账号或密码错误: 账号密码正确:跳转到…...
生成式 AI 增强了个人创造力,但减少了新内容的集体多样性
创造力是人类的核心。生成式人工智能 (AI)(包括强大的大型语言模型 (LLM))有望让人类通过提供新想法来更具创造力,或者通过锚定生成式 AI 想法来降低创造力。我们在一项在线实验中研究了生成式 AI 想法对短篇小说制作的因果影响,其中一些作家从 LLM 那里获得了故事创意…...
【DC简介--Part1】
DC简介-Part1 1 overview1.1 DC操作步骤1.2 Steps1.2.1 Develop HDL files1.2.2 Specify libraries1.2.3 Read design1.2.4 Define design environment1.2.5 Set design constraints1.2.6 Select compile strategy1.2.7 Synthesize and optimize the design1.2.8 Analyze and r…...
Spark写入HDFS数据SUCCESS文件生成控制
Spark写入HDFS数据SUCCESS文件 1、_SUCCESS的控制2、_SUCCESS的实现 1、_SUCCESS的控制 与Hive不同,MapReduce和Spark在执行写入HDFS数据任务时,数据输出目录一般都会有一个名为_SUCCESS的空文件,该文件仅用来表示任务执行成功 但有些时候&a…...
MySQL 服务器简介
通常所说的 MySQL 服务器指的是mysqld程序,当运⾏mysqld后对外提供MySQL 服务,这个专题的内容涵盖了以下关于MySQL 服务器以及相关配置的内容,包括: 服务器⽀持的启动选项。可以在命令⾏和配置⽂件中指定这些选项。 服务器系统变…...
如何使用Python从SACS结构数据文件中提取节点数据信息并导出到EXCEL
在现代工程设计中,结构分析和数据处理是不可或缺的一部分。特别是在海洋工程、桥梁建设等领域,SACS文件被广泛应用。这种文件格式包含了结构模型的各种重要信息,包括节点(JOINT)、构件(ELEMENT)…...
Java网约车项目实战:实现抢单功能详解
在网约车项目中,抢单功能是非常关键的一部分,它决定了司机能否及时响应乘客的订单,提高整个平台的运营效率。本文将详细介绍如何使用Java来实现网约车项目的抢单功能,并提供一个完整的代码示例,以便读者能够直接运行和…...
SSRF服务端请求Gopher伪协议白盒测试
前言 是什么SSRF? 这个简单点说就是 服务端的请求伪造 就是这个如果是个 请求图片的网站 他的目的是请求外部其他网站的 图片 但是 SSRF指的是让他请求本地的图片 再展示出来 请求的是他的服务器上的图片 SSRF(Server-Side Request Forgery:服务器端请求伪造) …...
html+css+js网页设计 美食 家美食1个页面
htmlcssjs网页设计 美食 家美食1个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1…...
初学stm32---高级定时器输出n个pwm波
目录 高级定时器简介:(F1) 高级定时器框图 重复计数器特性 高级定时器输出指定个数PWM实验原理 高级定时器输出指定个数PWM实验配置步骤 相关HAL库函数介绍 关键结构体介绍 高级定时器简介:(F1) 1.高级定时器 :TIM1/TIM8 2.主要特性&…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
