用于处理数据库中可排序项的高效且正确的策略

问题描述 投票:3回答:3

在Web应用程序中,我在数据库中有一组实体,其中一个数字字段负责它们的排序。在客户端,这些实体显示为可排序列表,允许用户更改其订单。

截至目前,我有两个管理订单更新的解决方案,但没有一个满足我。

第一个很简单:每次用户更改某个项目顺序时,遍历更新列表,将所有项目ID转换为数组,将其发送到服务器并发出一系列更新,其中每个项目顺序是它在数组中的ID索引。 这种方法的缺点是:许多不必要的更新,无法正确处理发送到服务器的项目数组不包含所有实体ID时的情况。

第二个是如下:当用户更改项目订单时,更改项目的ID将与ID中的项目ID一起发送到服务器,这些项目在其列表中的新位置“环绕”已更改项目。在服务器项目上,新订单由(previous.order + next.order) / 2计算。因此,如果订单3的商品在订单5和6的商品之间移动,则新订单将变为5.5 这个解决方案每次更改只需要一次更新,但也有一个严重的问题:由于使用的算法,每次更改都会增加订单号中的小数部分,迟早它需要更高的精度然后我的数据库才能提供(我在这种情况下使用MongoDB但是我想这并不重要)。

我的问题是,是否存在任何其他更有效和正确的方法,或者我现在的方法可能会以某种方式得到改善?

algorithm sorting database-design
3个回答
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
投票

我做了类似于你的第二种方法。虽然不是使用双打,但我使用整数并将项目间隔1000.这在我的应用程序中适用于我,因为项目数量不会超过4M。之后,当我确定增量现在已降至1(或小的某个)时,我会发出一个重置命令,将间隔重置为1000。我是用TSQL做的。

希望这可以帮助!


1
投票

您可以在数据库中使用链接列表:丢失订单列,并在该行上存储上一个项目ID或下一个项目ID。 然后更新是微不足道的(但显示已排序的列表的额外工作)。

© www.soinside.com 2019 - 2024. All rights reserved.