app端保存搜索记录

发布时间:2024年01月13日

? ? ? ? 今天要谈的是app端,或者说小程序端搜索记录的保存和显示,因为这种数据比较多,然后也会截取10条作为常规显示,所以这里用的是mongodb
? ? ? ? 搜索记录是根据时间排名的,如果新的搜索记录产生在第10位,他将会替换掉原本第10条的记录,所以这里会用到mongodb的一些增删查改的api,包括替换什么的
? ? ? ? 先上保存搜索记录到mongodb的代码
?

	/**
	 * 保存用户搜索历史记录
	 * @param keyword
	 * @param userId
	 */
	@Override
	@Async
	public void insert(String keyword, Integer userId) {
		//1.查询当前用户的搜索关键词
		Query query = Query.query(Criteria.where("userId").is(userId).and("keyword").is(keyword));
		ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);

		//2.存在 更新创建时间
		if (apUserSearch!=null){
			apUserSearch.setCreatedTime(new Date());
			mongoTemplate.save(apUserSearch);
			return;
		}
		//3.不存在,判断当前历史记录总数量是否超过10
		apUserSearch = new ApUserSearch();
		apUserSearch.setUserId(userId);
		apUserSearch.setKeyword(keyword);
		apUserSearch.setCreatedTime(new Date());

		Query query1 = Query.query(Criteria.where("userId").is(userId));
		query1.with(Sort.by(Sort.Direction.DESC,"createdTime"));
		List<ApUserSearch> apUserSearchList = mongoTemplate.find(query1, ApUserSearch.class);

		if (apUserSearchList==null||apUserSearchList.size()<10){
			mongoTemplate.save(apUserSearch);
		}else {
			ApUserSearch lastUserSearch = apUserSearchList.get(apUserSearchList.size() - 1);
			mongoTemplate.findAndReplace(Query.query(Criteria.where("id").is(lastUserSearch.getId())),apUserSearch);
		}
	}

? ? ? ? 这里涉及到一点,就是不同的用户,他保存的库是不一样的,这里用的是threadlocal来区分,就是threadlocal里的map,建为固定常量,比如就是threadlocal,值为用户id,即userid,所以,下述代码分别描述将userid放入请求头,还有从拦截器拿出,放入threasdlocal,方便后面使用
? ? ? ? 将唯一标识放入请求头
?

//当前代码为搜索服务坐在网关的部分代码,供参考,可在评论区留言要完整代码
            //获取用户信息
            Object userId = claimsBody.get("id");

            //存储header中
            ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {
                httpHeaders.add("userId", userId + "");
            }).build();
            //重置请求
            exchange.mutate().request(serverHttpRequest);

? ? ? ? 从拦截器获取唯一标识,放入threadlocal,这里注意,因为threadlocal中涉及到一个有可能值消失,键不能被删除的情况,所以这里在最后要将threadlocal清理掉,防止内存泄漏
?


@Slf4j
public class AppTokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //得到header中的信息
        String userId = request.getHeader("userId");
        Optional<String> optional = Optional.ofNullable(userId);
        if(optional.isPresent()){
            //把用户id存入threadloacl中
            ApUser apUser = new ApUser();
            apUser.setId(Integer.valueOf(userId));
            AppThreadLocalUtil.setUser(apUser);
            log.info("apTokenFilter设置用户信息到threadlocal中...");
        }

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("清理threadlocal...");
        AppThreadLocalUtil.clear();
    }
}

? ? ? ? 然后继续说保存搜索记录拿到唯一标识以后,即userid,就可以通过mongodb的api获取当前线程,当前用户得1搜索记录,如果当前搜索记录比10小,那么就可以将当前搜索关键字加到搜索记录内
? ? ? ? 如果当前搜索记录数量大于10,就将当前搜索记录的最后一项换成当前搜索关键字,这就是保存搜索记录的过程
? ? ? ? 这一块是异步调用的,所以要在搜索模块启动类和保存方法上加上异步标识,
? ? ? ? 然后,需要在文章搜索实现类中调用这个保存搜索记录的方法,我在之前的内容里有提到过,感兴趣的小伙伴可以去看看,只需要把下述代码放在检查参数和设置查询条件当中就可以了,具体的可以在评论区中提问

			ApUser user = AppThreadLocalUtil.getUser();
			//异步调用 保存搜索记录
			if (user!=null&&dto.getFromIndex()==0){
				apUserSearchService.insert(dto.getSearchWords(), user.getId());
			}


? ? ? ? 经过这一系列操作以后,就可以在mongodb的工具上看到你搜索过的词条,如下图所示

? ? ? ? 这里说一句,很多小伙伴会面临选择mongodb连接工具的情况,我这里推荐一款还不错的,叫做mongodb compass,感兴趣的小伙伴可以看看,免费,静默安装,给人感觉还不错,不是打广告哦
?????????

? ? ? ? ?接下来就是搜索列表的展示,其实也很好理解,他只是将当前线程的搜索记录按照递减创建时间展示出来,下面是代码
?

	@Override
	public ResponseResult findUserSearch() {
		//获取当前用户
		ApUser user = AppThreadLocalUtil.getUser();
		if (user!=null){
			//根据用户查询数据,按照时间倒序
			List<ApUserSearch> apUserSearches = mongoTemplate.find(Query.query(Criteria.where("userId").is(user.getId())).with(Sort.by(Sort.Direction.DESC, "createdTime")), ApUserSearch.class);
			return ResponseResult.okResult(apUserSearches);
		}
		return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
	}
}

? ? ? ?最后得到的效果如下

????????上述就是app,小程序端搜索记录的保存和展示,一键三连,欢迎各位小伙伴在评论区激烈讨论,也可以给我留言,我们一起探讨探讨

文章来源:https://blog.csdn.net/2301_82147294/article/details/135562239
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。