Database design 如何在排序列表中移动元素并保持CouchDb write;原子的;

Database design 如何在排序列表中移动元素并保持CouchDb write;原子的;,database-design,data-structures,transactions,couchdb,atomicity,Database Design,Data Structures,Transactions,Couchdb,Atomicity,我在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", "s

我在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 }
视图检索所有“列表”文档并按“排序”显示它们

现在我想移动元素,当我想将“jack”移到中间时,我可以在一次写入中完成这个原子,并将其排序键更改为105.0。视图现在以新的排序顺序返回文档

经过大量的排序后,我可能会在几年后得到像50.99999和50.99998这样的排序键,在极端情况下,数字会用完吗

你能推荐什么,有没有更好的方法?我宁愿将这些元素保存在单独的文档中。不同的用户可能并行编辑不同的列表元素

用户也可能同时更改文档顺序(当两个用户想要同时将两个不同的文档(如joey和jill)移动到末尾,比如说“sort”=130.0时,这也会变得很棘手)

也许有更好的方法


我错过了CouchDb事务吗?

当前系统真的是原子的吗?毕竟,要让杰克在乔伊和吉尔之间移动,我们需要知道乔伊和吉尔的价值观,这就要求他们首先被询问。在计算105.0之间,乔伊和吉尔的值也发生了变化,这是完全可行的。事实上,我相信在sqlland中唯一可行的方法是在重新排序时锁定相关行,从而导致重新排序请求的序列化


也许关于这个问题的更多细节会更有用。

您正在使用实数的通用模式来控制排序。 这是一项很好的技术,由Damien Katz推荐。要在相邻文档
A
B
之间移动,请将
sort
字段设置为
A.sort
B.sort
的平均值

这个问题有几个部分

浮点精度呢? Javascript
Number
s是双精度IEEE-754浮点数。他们 精度有限

双打的精确度很高。如果这是人类发起的活动,那么它 在拖放达到极限之前需要很长时间。 但你有两个选择:

1.在后台重新规范化排序值 还记得在BASIC中重写行号吗?同样的事情

从事cron工作或其他任务(越来越流行) 检查不可接受的关闭排序值并将其隔开。这 可以使用复杂的启发式方法,例如:

  • 等待站点处于低活动状态以修复排序
  • 在修复其
    sort
    s之前,请等待特定用户处于非活动状态X时间
  • 只进行空格
    排序
    值但从不更改的修改 查看结果。换句话说,如果您有
    0.001
    0.002
    0.003
    , 首先将
    0.003
    移动到例如
    0.100
    ,然后将
    0.002
    更改为
    0.005
    。那个 在UI中可能会有轻微的帮助,但请记住,复制可能不会 以相同的顺序复制这些内容,这样做的好处是微乎其微的,也许不值得 复杂性
2.使用精度不受限制的十进制数据类型 它可以存储来自的字符串,而不是存储Javascript
Number
但不包括
“0.0”
“1.0”
(例如,到100位)。然后使用字符串排序 也是数字排序。(0.0和1.0处的“锚定”对文档无效。若要在第一个位置插入文档,请将
sort
设置为0.0和当前第一个文档的平均值。对于最后一个位置,
sort
是最后一个文档和1.0的平均值。)

接下来,您的客户机(计算排序值的人)需要 任意精度实数类型。Java、Ruby、Python,几乎所有 语言有它们。这篇文章甚至激励我做一个快速的项目, 哪个是
BigDecimal
来自GoogleWebToolkit(它本身来自ApacheHarmony)的代码。但是那里 还有其他的实现

我个人喜欢
BigDecimal
。然而,在你的情况下,你必须改变你的想法 使用字符串进行排序的代码。不管好处是什么,你永远不必重新正常化
排序
s以绕过精度

那么并发活动的冲突呢? CouchDB很放松。将会发生的事情是用户所期望的。CouchDB 文档模仿真实世界。正如克里斯·安德森所说,“没有 现实生活中的交易。”

对于UI中的三个元素:

  • 项目a
  • 项目B
  • 项目C
如果我将
A
移到
C
之后,而你将
B
移到C之后,该怎么办?显然,名单要么是
cba
cba
。应该是哪一个?这取决于你的申请

或者,没关系:太好了!CouchDB将任意订购
A
B
,而您 好的。用户将推断(或查看您的UI是否良好)其他人移动了 另一项

或者,B必须在A之前,因为[某种原因]:那么,您的
排序值是错误的。
它应该包括所有相关数据以决定子类别。例如,你可以
emit([120.000,doc.userLastName],doc)
。当用户将文档移动到同一位置时 排序变成字母顺序

如果您说,A不能在B移动后这么快移动,那么这也是应用程序 无论数据存储是什么,都必须实现的代码。换句话说,它不是 一个事务性的东西,它是软件逻辑。用于拖放UI元素, 我的感觉是,这不值得,而“没关系”的解决方案是最好的。

什么