实现收藏功能

一、问题描述

在日常使用的app中,基本都会有【收藏】功能,本文将介绍项目实战过程中收藏功能所采用的技术方案,其核心思想为使用【快照】,快照可采用json实现。

二、功能实现

2.1表设计

数据表的核心字段为用户iduserId、业务IDbusinessId、快照信息snapshot、收藏内容类型 type、收藏状态status。数据表DDL如下:

create table t_favorite
(
    id          bigint auto_increment comment '主键'
        primary key,
    userId      bigint                not null comment '用户id',
    business_id varchar(64)           not null comment '业务ID',
    `snapshot`    json                  not null comment '快照信息',
    `status`      int        default 0  not null comment '变更状态,如已下架',
    `type`        varchar(8) default '' not null comment '收藏类型',
    ...
    constraint uk_userid_type_businessid
        unique (user_id, `type`, business_id)
)
    comment '收藏夹';

数据表使用用户id、收藏类型、业务id作为唯一索引,用以防止用户快速多次点击导致的重复收藏问题,也可考虑其他防重方案,如前端防重、分布式锁等。

2.2代码实现

2.2.1实体类

收藏实体类如下所示:

public class Favorit {
	private Long id;
	private Long userId;
	private String businessId;
	@TableField(typeHandler = FastjsonTypeHandler.class)
	private JSONObject snapshot;
	private String type;
	private Integer status;
}

snapshot字段注解需要实现配置类,具体可参考文章:MySQL存入和解析JSON字符串
入参类如下所示:

@Data
public class FavoriteReq {
    private Long userId;
    private String businessId;
    private JSONObject snapshot;
    private Integer status;
    private String type;
    private Long minId;
    private List<Long> businessIds;
}

2.2.2分页实现

收藏列表一般为按收藏时间倒序查询,即自增id由小到大排序,由此,为提升分页查询效率,可采用最小IDminId来做分页,具体如下:

  • 假设分页大小为每页10条数据;
  • 首次查询时minId传0,可以拿到当前收藏的id最大的10条数据,后续查询时minId为上一次查询查到的最小id;
  • 例:有100条数据,首次查询时传minId为0,查到数据的id范围为100-91,则第二次查询时minId为91,查到的数据id范围为90-81,以此类推,即可实现分页。

分页代码如下:

public List<Favorite> listFavorite(FavoriteReq favoriteReq) {
        Page<Favorite> page = new Page(1, 10);
        LambdaQueryWrapper<Favorite> wrapper = Wrappers.lambdaQuery(Favorite.class)
                .eq(Favorite::getUserId, favoriteReq.getUserId())
                .eq(Favorite::getType, favoriteReq.getType())
                .eq(favoriteReq.getBusinessId() != null, Favorite::getBusinessId, favoriteReq.getBusinessId())
                .lt(favoriteReq.getMinId() != null && favoriteReq.getMinId() > 0 ,Favorite::getId, favoriteReq.getMinId())
                .orderByDesc(Favorite::getId);
        List<Favorite> favorites = favoriteRepository.list(page, wrapper);
        return favorites;
    }

2.3分库分表方案

TODO。。。

三、结果示例

postman调用查询结果如下所示:

{
    "code": "200",
    "message": "ok",
    "extraCode": "",
    "extraMessage": "",
    "tracestack": null,
    "url": null,
    "data": [
        {
            "businessId": "1234",
            "snapshot": {
                "title": " 菜篮子",
                "firstCategoryName": "餐饮",
                "telPhone": "12345678900",
                "infoDTO": {
                    "salesTips": "半年销量500+",
                    "subTitle": "",
                    "submitJumpUrl": "https://www.baidu.com",
                    "tag": "",
                    "title": "",
                    "support": 0
                }
            },
            "status": 1,
            "type": "brand",
            "id": "25"
        }
    ]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码不停蹄的玄黓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值