{ "id" : "783587346","type" : "aList","content" : "joey","sort" : 100.0 } { "id" : "358734ff6","content" : "jill","sort" : 110.0 } { "id" : "abf587346","content" : "jack","sort" : 120.0 }
视图检索所有“aList”文档,并按“sort”排序显示.
现在我想移动元素,当我想要将“jack”移动到中间时,我可以在一个写入中做这个原子,并将它的排序键改为105.0.现在,视图以新的排序顺序返回文档.
经过大量的排序,我可以在多年后最终得到类似于50.99999和50.99998的排序键,而在极端情况下,可能会出现数位问题?
有什么建议,有没有更好的方法呢?我宁愿将元素保存在单独的文档中.不同的用户可能并行编辑不同的列表元素.
用户也可能会同时更改文档顺序(当用户想要移动两个不同的文档(如joey和jill)时,同时也可能会出现棘手的问题,比如说“sort”= 130.0同时).
也许有更好的方法?
我在CouchDb交易中错过了什么吗?
解决方法
这是一个很好的技术,由Damien Katz推荐.要在相邻文档A和B之间移动,您将排序字段设置为A.sort和B.sort的平均值.
这个问题有几个部分.
浮点精度怎么样?
Javascript数字是双精度IEEE-754浮点数.他们
精度有限.
双打有很多精度.如果这是人类发起的活动的话
在拖放之前会很长时间才能达到极限.
但你有两个选择:
1.在后台重新规范排序值
记得在BASIC中重写行号吗?一样.
有一个cron工作或其他任务(NodeJS越来越受欢迎)
检查不可接受的紧密排序值,并将其排出.这个
可以使用复杂的启发式,如:
>等到站点处于低活动状态以解决问题
>等待直到特定用户在固定他的排序之前为X时间无效
>只做修改,排除排序值,但从不改变
查看结果.换句话说,如果你有0.001,0.002和0.003,
将0.003首先移至例如0.100,然后更改0.002至0.005.那
可能在UI中有一些有用的效果,但请记住,复制可能不会
以相同的顺序复制这些,以便利益是边缘的,也许不值得
复杂性.
2.使用无限精度的十进制数据类型
而不是排序存储一个Javascript号码,它可以存储一个字符串
但不包括“0.0”到“1.0”(比如100位数字).然后一个字符串排序是
也是数字排序. (您的“锚”为0.0和1.0,对文档无效.要将文档插入到第一个位置,请将排序设置为0.0和当前第一个文档的平均值.对于最后一个位置,排序是最后一个文件和1.0.)
接下来,您的客户端(谁计算排序值)需要
任意精度实数类型. Java,Ruby,Python,几乎全部
语言有它们.这个帖子甚至启发我做一个快速的项目,
BigDecimal for Javascript是BigDecimal
来自Google Web Toolkit(本身来自Apache Harmony)的代码.但在那里
也是其他的实现.
我个人喜欢BigDecimal.在你的情况下,你必须改变你的
代码使用字符串进行排序.但是好处是,你不必重新规范化
排序精准.
并发活动的冲突呢?
CouchDB放松了会发生什么是用户期望的CouchDB的
文件模仿现实世界.正如克里斯·安德森所说:“没有
现实生活中的交易“.
对于UI中的三个元素:
> ItemA
> ItemB
> ItemC
如果我在C之后移动A并且在C之后移动B,该怎么办?显然,这个名单将会是
C B A或C A B.应该是哪一个?这取决于你的应用程序?
无论如何,没关系:太好了! CouchDB将随意订购A和B
会没事的.用户会推测(或看看您的用户界面是否好)
另一个项目.
或者,B必须来到A之前,因为[某些原因]:那么你的排序值是错误的.
它应包括所有相关数据来决定分类.例如,你可以
emit([120.000,doc.userLastName],doc).当用户将文档移动到同一个地方时,
排序变得字母顺序.
如果你说,A不能移动这么快之后,B移动,那也是应用程序无论数据存储如何,必须执行代码.换句话说,这不是一个事务性的事情,它是软件逻辑.对于拖放UI元素,我的感觉是,这不值得,“没关系”解决方案是最好的.