看板软件,相信大多人都用过类似的软件,主要就是卡片拖动,卡片可以左右拖动,上下拖动,后端如何实现才能做到不用每次重排序号从而提高性能呢,在企业软件中也有很多树形和列表都是支持拖动排序的,这样设计比传统的上下直接移动可以提高效率,所以很多时候产品经理会合理考虑使用拖动排序来提高用户体验度。

今天就来思考一下后端如何实现呢?前端相信有一些现成的组件可以直接使用,在此就不去找了~

类似于某看板如下图:
拖拽排序后端实现方案思考

再或者这种列表拖动:

拖拽排序后端实现方案思考

数据库设计

根据实际需要肯定至少序号3个字段、(id:主键、sort:排序号、name:展示名称),其他字段就根据自己的业务需要进行设计,针对后续不同方案有调整,请看具体的方案数据库改动。

实现方式

一、全量更新

这种方式估计大多数人都能考虑到的,就根据前端传入的拖动的id和目标的id,为了方便描述,我统一以列表形式进行展示,在这里不管是往前拖动还是往后拖动,我们只需要完成拖动后找到发生改变后面的序号,然后全部对sort字段进行重排序即可。

二、间隔取中值法

这种办法是在方法一的基础上进行优化,主要是为了解决频繁的拖动导致每次都要重刷sort序号,对于高频繁的接口容易对数据库造成很大的压力,所以间隔取中值法就是为了一定程序上解决数据库发生重排的情况。

首先确定业务拖动的频率,一般间隔1024~65535完全够用了,我这里就用间隔1024来举例,在新增数据的时候自动计算出序号,比如数据库现在有10个数据,那么新增的时候算出的sort=(10+1)× 1024,然后保存为新增的时候sort。

在拖动的时候,分为三种情况:
1、调整一个元素到两个元素中间时,那么就是直接将拖动的那条数据sort=两条数据之和 ÷ 2更新到数据库即可。
2、调整一个元素到第一个元素上方时,那么就是直接将拖动的那条数据sort=第一条数据sort ÷ 2然后保存到数据库即可。
3、调整一个元素到最后一个元素下方时,那么就是直接将拖动的那条数据sort=最后那条数据sort + 1024然后保存到数据库即可。

通过此方法在一定程度上能够缓解频繁的重排序问题,但是也会有一些极限问题需要每次校验是否达到了临界值,因为每次取中值,每次都会进行平分间隔值,一直拖动就会导致这个值越来越趋近与相等,所以还要考虑以下情况。

1)判断当最小sort和最大sort不在 2 到 sort所定的类型最大值(Integer.MAX_VALUE或者Long.MAX_VALUE)减间隔值 之间的时候,就对数据全部重排序依次,让再下次即便拖动到第一个的上方也不会出现两个sort相等,从而导致排序失效;

2)判断调整一个元素到两个元素中间时时候,最终要更新拖拽sort加减1是否等于两个元素的值,如果等于了就立刻对数据进行重排;

三、字符串排序

此方式只能针对数据库唯一主键比较短、数据量不大的情况,并且分为主子表的情况,直接将最终的排序记录以逗号或者|符号进行存储在主表的字段上,每次拖动的时候直接由前端传入字符串保存即可,无需关心子表的sort,每次查询之后进行排序,也不存在需要重排序的问题,主要靠前端进行更新排序字段。

四、双向链表

这种方法就需要在数据库增加2个字段,pre_sort、next_sort、记录前后2个节点的值,然后每次改动直接只需要进行改变涉及到的3个元素的值,操作数据库最大为6次,最小操作为4次,但是此方案受限于无法对数据库进行分页和排序。

接口设计

针对采用不同的方法方案接口设计都不一致,我们只需要让前端传入必须传的参数即可,能不信任前端用户传的值就不信,最好自己从数据库进行验证和查询。

我这里给一种常规方案二的接口设计,需要三个字段dragId:拖动的元素id、targetId、拖拽到目标位置的id、moveType:移动类型(UP/DOWN),这样可以灵活的移动到目标的位置上下方都可以。

总结

具体选择方案根据我们的数据量来,比如像支付宝淘宝支付方式的快捷拖动优先级,本身支付方式就有限并且拖动操作不是很频繁的操作,我们直接每次进行刷新也无所谓,但是如果是需要在前面给用户展示的树形层级列表等,我们尽量做到少去刷数据库,然后在查询的时候不需要的额外在内存处理,支持分页方案,我这里个人中小体量业务使用间隔取中值法很合适,使用间隔65535的话可以在很长时间不需要去刷新数据库,如果你想再减少在用户量大的时候刷新数据库数据,那么你再加上夜间定时任务全部重刷能进一步减少。网上的方案许多许多,若需要深入了解可以看下文章末参考链接,若你有更好的方案欢迎评论区留言一起探讨。

参考链接

拖拽数据库设计方案小结-腾讯云开发者社区-腾讯云
teambition的任务卡排序,数据是怎么存储的? - 知乎
拖拽排序后端设计与实现 - 简书
工作实践:拖拽排序的后端实现 - 掘金
设计一个通用的排序方案,关于模糊中间数的计算思路 - 掘金
使用React DnD实现列表拖拽排序-腾讯云开发者社区-腾讯云

文章目录