我在 couchdb 文档中有一个列表元素。假设这些是 3 个文档中的 3 个元素:
{ "id" : "783587346", "type" : "aList", "content" : "joey", "sort" : 100.0 }
{ "id" : "358734ff6", "type" : "aList", "content" : "jill", "sort" : 110.0 }
{ "id" : "abf587346", "type" : "aList", "content" : "jack", "sort" : 120.0 }
View 检索所有“aList”文档并按“sort”排序显示它们。
现在我想移动元素,当我想将“jack”移动到中间时,我可以在一次写入中完成这个原子并将其排序键更改为 105.0.0。该 View 现在以新的排序顺序返回文档。
经过大量排序后,我可能会在几年后得到像 50.99999 和 50.99998 这样的排序键,并且在极端情况下会用完数字?
你能推荐什么,有没有更好的方法来做到这一点?我宁愿将元素保存在单独的文档中。不同的用户可能会并行编辑不同的列表元素。
并且用户也可能同时更改文档顺序(当 2 个用户想要将两个不同的文档(如 joey 和 jill)移动到末尾时,例如“sort” = 130.0,这也会变得棘手)。
也许有更好的方法?
我是否错过了 CouchDb 交易中的某些内容?
最佳答案
您正在使用实数的常见模式进行排序的用户控制。
这是一项很好的技术,由 Damien Katz 推荐。在相邻文档之间移动 A
和 B
,然后你设置你的 sort
场的平均值 A.sort
和 B.sort
.
这个问题有几个部分。
浮点精度怎么样?
Javascript Number
s 是 double IEEE-754 浮点数。他们
精度有限。
double 精度很高。如果这是人类发起的事件,那么它
拖放操作将需要很长时间才能达到极限。
但是你有两个选择:
1.在后台重新归一化排序值
还记得用 BASIC 重写你的行号吗?一样。
有一份 cron 工作或其他一些任务(NodeJS 越来越受欢迎)
检查 Not Acceptable 接近排序值并将它们隔开。这个
可以使用复杂的启发式方法,例如:
sort
s sort
s sort
值(value),但永远不会改变查看结果。换句话说,如果您有
0.001
, 0.002
, 和 0.003
,移动
0.003
首先到例如0.100
,然后更改 0.002
至 0.005
.那可能对 UI 有一点帮助,但请记住,复制可能不会
以相同的顺序复制这些,所以好处是微不足道的,也许不值得
复杂性。
2. 使用具有无限精度的十进制数据类型
而不是
sort
存储 Javascript Number
,它可以存储一个字符串但不包括
"0.0"
通过 "1.0"
(比如说,到 100 位数字)。那么一个字符串排序是也是数字排序。 (您在 0.0 和 1.0 处有对文档无效的“ anchor ”。要在第一个位置插入文档,请将
sort
设置为 0.0 和当前第一个文档的平均值。对于最后一个位置,sort
是最后一个文档的平均值和 1.0。)接下来,您的客户(计算
sort
值的人)需要任意精度实数类型。 Java、Ruby、Python,几乎所有
语言有它们。这篇文章甚至激励我做一个快速的项目,
BigDecimal for Javascript这是
BigDecimal
代码来自 Google Web Toolkit(它本身来自 Apache Harmony)。但是有也是其他实现。
我个人喜欢
BigDecimal
.但是,在您的情况下,您将不得不更改您的为
sort
使用字符串的代码.然而好处是,你永远不必重新规范化sort
s 解决精度问题。来自并发事件的冲突呢?
CouchDB 是放松的。将会发生什么是用户所期望的。沙发数据库
文档模仿现实世界。正如克里斯·安德森所说,“没有
现实生活中的交易。”
对于 UI 中的三个元素:
如果我搬家怎么办
A
之后 C
你搬家B
在 C 之后?显然,该列表要么是C B A
或 C A B
.应该是哪个?这取决于您的应用程序?要么,没关系 : 伟大的! CouchDB 将订购
A
和 B
随意而你会没事的。用户会推断(或查看您的 UI 是否良好)其他人移动了
另一个项目。
或者, B 必须在 A 之前,因为 [某些原因] : 那么,你的
sort
值不对。它应该包括所有相关数据来决定子分类。例如,您可以
emit([120.000, doc.userLastName], doc)
.当用户将文档移动到同一位置时,sort 按字母顺序排列。
如果你说, B 搬家后 A 不能这么快搬家 那么这也是应用
无论数据存储如何,都必须实现的代码。换句话说,它不是
一个事务性的东西,它是软件逻辑。对于拖放 UI 元素,
我的感觉是,这不值得,“没关系”的解决方案是最好的。
关于database-design - 如何移动排序列表中的元素并保持 CouchDb 写入 "atomic",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2940329/