如何在排序列表中移动元素并保持CouchDb写入"原子"

use*_*021 15 database-design couchdb transactions atomicity data-structures

我在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 }
Run Code Online (Sandbox Code Playgroud)

视图检索所有"aList"文档并按"sort"排序显示它们.

现在我想移动元素,当我想将"jack"移动到中间时,我可以在一次写入中执行此原子操作并将其排序键更改为105.0.视图现在以新的排序顺序返回文档.

经过大量的排序后,我可能会在几年后使用50.99999和50.99998之类的排序键,并且在极端情况下会耗尽数字?

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

用户也可能同时更改文档顺序(当2个用户想要将两个不同的文档(如joey和jill)移动到最后时,也可能会变得棘手,让我们说"sort"= 130.0同时).

也许有更好的方法?

我错过了CouchDb交易的内容吗?

Jas*_*ith 20

您正在使用实数的通用模式来进行用户对排序的控制.这是一个很好的技术,Damien Katz推荐.相邻的文档之间进行切换A,并B,然后您将设置sort场平均的A.sortB.sort.

这个问题有几个部分.

浮点精度怎么样?

Javascript Number是双精度IEEE-754浮点数.它们的精度有限.

双打有很多精确度.如果这是人为启动的活动,那么在拖放达到极限之前将是很长时间.但你有两个选择:

1.在后台重新规范化排序值

还记得在BASIC中重写你的行号吗?一样.

有一个cron作业或其他任务(NodeJS越来越流行)来检查不可接受的接近排序值并将它们分开.这可以使用复杂的启发式,例如:

  • 等到站点活动不足以修复sorts
  • 等到特定用户在修复他sort的时间之前处于非活动状态X时间
  • 仅进行修改,这些修改会使sort值超出但不会更改视图结果.换句话说,如果你有0.001,0.0020.003,将第0.003一个移到eg 0.100,然后0.002改为0.005.这可能会对用户界面产生轻微的帮助,但请记住,复制可能不会以相同的顺序复制这些,因此利益是微不足道的,也许不值得复杂.

2.使用无限精度的十进制数据类型

它可以存储一个字符串, 但不包括通过(例如,100个数字),而不是sort存储Javascript .然后字符串排序也是数字排序.(你有0.0和1.0的"锚点"对文档无效.要在第一个位置插入文档,设置为0.0的平均值和当前的第一个文档.对于最后一个位置,是最后一个文档的平均值和1.0.)Number "0.0""1.0"sortsort

接下来,您的客户端(无论谁计算该sort值)都需要任意精度的实数类型.Java,Ruby,Python,几乎所有语言都有它们.这篇文章甚至激励我制作一个快速项目, BigDecimal for Javascript,这是BigDecimal 来自Google Web Toolkit 的代码(它本身来自Apache Harmony).但也有其他实现.

我个人喜欢BigDecimal.但是,在您的情况下,您必须更改代码以使用字符串sort.然而,好处是,您永远不必重新规范化sorts以解决精度问题.

并发活动的冲突怎么样?

CouchDB很轻松.会发生什么是用户期望的.CouchDB文档模仿现实世界.正如克里斯安德森所说,"现实生活中没有任何交易."

对于UI中的三个元素:

  • 意达
  • ItemB
  • ItemC

如果我移动AC你移动BC怎么办?显然,该列表将是 C B AC A B.应该是哪个?这取决于你的申请?

要么,没关系:太好了!CouchDB将任意订购A,B你会没事的.用户将推断(或查看您的UI是否良好)其他人移动了其他项目.

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

如果你说,A移动后不能很快移动A那么这也是必须实现的应用程序代码,无论数据存储如何.换句话说,它不是事务性的东西,而是软件逻辑.对于拖放UI元素,我的感觉是,它不值得,"无关紧要"的解决方案是最好的.