2

我正在开发一个本质上与待办事项列表非常相似的应用程序,除了待办事项的顺序很重要并且可以由用户更改。

有什么好方法可以将此订单保存在数据库中,而无需在更改订单时重新保存整个待办事项列表?

我正在使用最新版本的 Rails、Postgres 和 React 进行开发。

我正在考虑将它保存为 User Todos 中的一个数组(应用程序可以有多个用户),但我认为它可能会使事情变得有点复杂,因为每次我创建一个 todo 时我都必须保存列表。

4

2 回答 2

1

您可以查看acts_as_list gem,为此您必须在表中添加一个额外的列位置。但这将对记录进行大规模更新。但是这个宝石经常更新。

如果您想要一个优化的解决方案并尽量减少更改列表的更新次数,那么您应该检查ranked_model gem,但这个不是经常更新。有一个关于它是如何工作的简介: -

这个库是从头开始使用 ARel 编写的。这使代码比许多实现更干净。rank-model 还优化为尽可能少地写入数据库:rank 存储为介于 -2147483648 和 2147483647 之间的数字(MySQL 中的 INT 范围)。当一个项目被赋予一个新位置时,它会在两个邻居之间为自己分配一个排名号。这允许在两个邻居之间没有可用的数字之前进行项目的多次移动。发生这种情况时,ranked-model 将尝试将其他记录移开。如果项目不能再轻易移动,它将重新平衡排名组所有成员的排名数字分布。

您可以参考此 gem 并自行实现,因为它仅支持 rails 3 和 4。

于 2017-07-02T20:09:39.083 回答
0

这有点让人头疼,但这是我的想法:

create table orderedtable (
   pk SERIAL PRIMARY KEY,
   ord INTEGER NOT NULL,
   UNIQUE(ord) DEFERRABLE INITIALLY DEFERRED
)

DEFERRABLE INITIALLY DEFERRED很重要,这样中间状态就不会在重新排序期间导致违反约束。

INSERT INTO orderedtable (ord) VALUES (1),(2),(3),(4),(5),(10),(11)

请注意,在此表中插入时,在值之间留出间隙会更有效,ord以最大限度地减少稍后插入或移动行时需要移动的顺序值的数量。连续值用于演示目的。

诀窍是:您可以使用递归查询找到从特定值开始的连续值序列。

例如,假设您想在位置 3 上方插入或移动一行。一种方法是将当前位于位置 4 和 5 的行向上移动一个以打开位置 4。

WITH RECURSIVE consecutives(ord) AS (
  SELECT ord FROM orderedtable WHERE ord = 3+1 --start position
UNION ALL
  SELECT orderedtable.ord FROM orderedtable JOIN consecutives ON orderedtable.ord=consecutives.ord+1 --recursively select rows one above, until there is a hole in the sequence
)
UPDATE orderedtable
SET ord=orderedtable.ord+1
FROM consecutives
WHERE orderedtable.ord=consecutives.ord;

上面将ordfrom1,2,3,4,5,10,11 重新编号为1,2,3,5,6,10,11在 4 处留下一个洞。如果在ord=4 处已经有一个洞,则上面的查询不会做任何事情。

然后通过给它现在的自由ord值 4 来插入或移动另一行。

您可以通过将 +1 更改为 -1 来向下而不是向上推动行。

于 2021-06-12T02:51:05.630 回答