文章目录
功能需求分析
1.允许用户传入多个标签,多个标签都存在才搜索出来 (目前做的是这个)
2.允许用户传入多个标签,有任何一个标签存在就能搜索出来
两种方式
1.sql查询
根据标签搜索用户业务逻辑(sql)(实现简单)
2.内存查询
内存查询业务逻辑
1.先查询所有用户
2.在内存中判断是否包含要求的标签(灵活)
解析json字符串
为什么需要解析json字符串?
内存中查询出来的一个用户的所有标签是json字符串格式的数据,需要把它解析成集合
什么是序列化反序列化?
序列化:java对象转成json
反序列化:把json转为Java对象
Java json序列化库:
1.fastjson
2.gson
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
3.jackson
4.kryo
内存查询代码
@Override
public List<User> searchUsersBytags(List<String> tags) {
if (CollectionUtils.isEmpty(tags)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// //从数据库中进行模糊查询
// QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// for(String tag : tags){
// queryWrapper.like("tags",tag);
// }
// List<User> userList = userMapper.selectList(queryWrapper);
// //脱敏
// return userList.stream().map(user -> getSafetyUser(user)).collect(Collectors.toList());
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
List<User> userList = userMapper.selectList(queryWrapper);
Gson gson = new Gson();
// for (User user : userList) {
//内存中用户的标签
// String Usertags = user.getTags();
// Set<String> tagSet = gson.fromJson(Usertags, new TypeToken<Set<String>>() {
// }.getType());
// tagSet = Optional.ofNullable(tagSet).orElse(new HashSet<>());
//遍历传入的标签列表,如果有一个标签用户不存在,就不行,全部存在才可以
// for (String tag : tags) {
// if (!tagSet.contains(tag)) {
// return false;
// }
// }
// return true;
// }
//语法糖
return userList.stream().filter(user -> {
String Usertags = user.getTags();
if (StringUtils.isBlank(Usertags)) {
return false;
}
Set<String> tagSet = gson.fromJson(Usertags, new TypeToken<Set<String>>() {
}.getType());
tagSet = Optional.ofNullable(tagSet).orElse(new HashSet<>());
for (String tag : tags) {
if (!tagSet.contains(tag)) {
return false;
}
}
return true;
}).map(user -> getSafetyUser(user)).collect(Collectors.toList());
// return userList.stream().map(user -> getSafetyUser(user)).collect(Collectors.toList());
}
如何选择
1.如果参数可以分析,根据用户的参数取选择查询方式,比如标签数
2.如果参数不可以分析。并且数据库连接足够,内存空间足够,可以并发同时查询,谁先返回用谁
3.还可以sql查询与内存运算结合,比如先用sql过滤掉部分tag
mybatis-plus开启查询日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
注意替换项目名
拉取别人的项目记得要ctrl + shift + r将文件名和代码中项目名替换为自己的
出现的小bug
//com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: One record is expected, but the query result is multiple records
//selectOne期望返回1但实际返回了多条
// User user = userMapper.selectOne(null);
接口实现
@GetMapping("/search/tags")
public BaseResponse<List<User>> searchUsersByTags(@RequestParam(required = false) List<String> tags) {
if(CollectionUtils.isEmpty(tags)){
return ResultUtils.error(ErrorCode.PARAMS_ERROR);
}
List<User> userList = userService.searchUsersBytags(tags);
return ResultUtils.success(userList);
}
java8 parallelstream的坑
线程安全问题,数据量小时造成性能开销