在Web应用程序中,我在数据库中有一组实体,其数字字段负责其排序。在客户端,这些实体显示为可排序列表,允许用户更改其订单。
截至目前,我有两个管理订单更新的解决方案,但没有一个能让我满意。
第一个很简单:每次用户更改某个项目顺序时,遍历更新列表,将所有项目ID转换为数组,将其发送到服务器并发出一系列更新,其中每个项目顺序是它在数组中的ID索引。
这种方法的缺点:许多不必要的更新,无法正确处理发送到服务器的项目数组不包含所有实体ID时的情况。
第二个如下:当用户更改项目订单时,更改项目的ID将与ID中的项目ID一起发送到服务器,这些项目位于列表中新位置的“已更改项目”。在服务器项目上,新订单由(previous.order + next.order) / 2
计算。因此,如果订单3的项目在订单5和6的项目之间移动,则新订单将变为5.5
该解决方案的每只需改变一次更新,但也有一个严重的问题:由于使用的每一个变化的算法,以数字增加了小数部分,迟早需要更多精密然后我的数据库可以提供(我使用MongoDB的这种情况,但我想这并不重要。)
我的问题是,是否存在任何其他更有效和正确的方法,或者我现在的方法可能会以某种方式得到改善?
答案 0 :(得分:5)
使用序号描述数据库中的顺序,该序号从第一项开始为0,对于每个后续项开始增加1。然后,您只需要发送已移动项目的序号,以及新上一个邻居的序号。然后你做(我用$来标记变量 - 你需要将它们传递给代码中的查询):
-- if $moved > $previous, and it's moving backwards, move everything between the new previous neighbour and the item forward one
update items
set ordinal = ordinal + 1
where ordinal > $previous
and ordinal < $moved;
-- else $moved < $previous, and it's moving forwards, move everything between the item and the new previous neighbour backwards one
update items
set ordinal = ordinal - 1
where ordinal > $moved
and ordinal <= $previous;
-- then move the item
update items
set ordinal = $previous + 1
where ordinal = $moved;
您可以为序数列添加唯一约束以帮助确保完整性,但您必须更加清楚地了解更新方式。
答案 1 :(得分:1)
我做了类似于你的第二种方法。虽然不是使用双打,但我使用整数并将项目间隔1000.这在我的应用程序中适用于我,因为项目数量不会超过4M。稍后,当我确定增量现在已降至1(或小的某个)时,我会发出一个重置命令,将间隔重置为1000。我是用TSQL做的。
希望这有帮助!
答案 2 :(得分:1)
您可以在数据库中使用链接列表: 丢失订单栏,并在该行上存储先前的商品ID或下一个商品ID 然后更新是微不足道的(但显示已排序的列表的额外工作)。