mongodb:建模用户定义的排序顺序

时间:2014-02-15 16:32:59

标签: mongodb sorting

我正在寻找一种实现排序键的好方法,这完全是用户可定义的。例如。向用户呈现列表,并且可以通过拖动它们来对元素进行排序。该命令应该保留。

一种常用的方法是在每个元素中创建一个升序整数类型排序字段:

{
    "_id": "xxx1",
    "sort": 2
},
{
    "_id": "xxx2",
    "sort": 3
},
{
    "_id": "xxx3",
    "sort": 1
}

虽然这肯定会起作用,但它可能并不理想:如果用户将元素从最底部移动到最顶部,则需要更新其间的所有索引。我们这里不讨论嵌入式文档,因此这将导致许多单个文档的更新。这可以通过创建具有间隙(例如,100,200,300,400)的初始排序值来优化。但是,如果两个元素之间的空间用尽,这将需要额外的逻辑和重新排序。

另一种方法是:让父文档包含一个已排序的数组,它定义了子类的顺序。

{
  "_id": "parent01",
  "children": ["xxx3","xxx1","xxx2"]
}

这种方法肯定会更容易更改顺序,但会有自己的警告:父文档必须始终跟踪其子项的有效列表。由于添加子项将更新多个文档,这仍然可能不太理想。并且需要对从客户端接收的输入进行复杂的验证,因为该列表的长度和包含的元素可能永远不会被客户端更改。

有没有更好的方法来实现这样的用例?

1 个答案:

答案 0 :(得分:2)

很难说不知道哪个选项更好:

  1. 排序顺序通常更新的频率
  2. 您要对文件进行哪些查询以及多长时间
  3. 一次可以分拣多少文件
  4. 我确信你会比更新做更多的查询,所以我个人会选择第一个选项。它易于实现,而且很简单,这意味着它将是反弹。我理解您对更新多个文档的担忧,但更新将在适当的位置完成,我的意思是不会发生文档转换,因为您实际上没有更改文档大小。只需创建一个简单的测试。生成1k个文档,然后在这样的循环中更新每个文档

    db.test.update({ '_id': arrIds[i] }, { $set: { 'sort' : i } })
    

    你会发现这将是一个非常即时的操作。

    我也喜欢第二个选项,从编程角度来看它看起来更优雅但是当涉及到练习时,如果你不经常这样做更新需要10毫秒而不是5,那么你通常不会太在意我“我相信你不会,大多数应用程序都是面向查询的。

    修改 当您更新多个文档时,即使它是即时操作,当某些文档更新而某些文档未更新时,可能会出现不一致问题。就我而言,事实上并不是真正的问题。让我们考虑一个例子,假设有一个列表:

    { "_id" : 1, "sort" : 1 },{ "_id" : 2, "sort" : 4 },{ "_id" : 3, "sort" : 2 },{ "_id" : 4, "sort" : 3 }
    

    所以根据排序字段,有序ID应该看起来像 1,3,4,2 。假设我们想将id = 2移到顶部,我们就失败了。当我们只更新两个文档时发生故障,因此我们将提出以下状态,因为我们只设法更新ID 2和1:

    { "_id" : 1, "sort" : 2 },{ "_id" : 2, "sort" : 1 },{ "_id" : 3, "sort" : 2 },{ "_id" : 4, "sort" : 3 }
    

    数据处于不一致状态,但我们仍然可以显示列表以解决问题,如果我们只按排序字段订购,则ID顺序为 2,1,3,4 。为什么在我的情况下不是问题?因为当发生故障时,用户被重定向到错误页面或提供错误消息,很明显他出错了,他应该再试一次,所以他只是去了页面并修复了只是部分的订单对他有效。

    总结一下。考虑到这是一个非常罕见的情况和该方法的其他好处,我会用它。否则,您必须将所有元素和数组及其索引放在一个文档中。这可能是一个更大的问题,尤其是在查询时。

    希望它有所帮助!