【问题标题】:mongodb: modelling user defined sort ordermongodb:建模用户定义的排序顺序
【发布时间】:2014-03-15 01:20:53
【问题描述】:

我正在寻找一种实现排序键的好方法,这是完全由用户定义的。例如。用户会看到一个列表,并且可以通过拖动元素来对元素进行排序。应该保持这个顺序。

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

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

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

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

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

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

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

【问题讨论】:

  • 第二个选项在我看来更加有效和可行。对从客户端接收到的输入进行复杂验证是什么意思?如果您只想检查客户端是否使用有效元素,您可以使用第二个单独的集合,其中仅包含有效元素来检查这一点。此外,mongodb 将很快就会在生产版本中添加“在索引处插入”选项 (jira.mongodb.org/browse/SERVER-2363)。
  • 谢谢,这个问题只会出现在允许客户端发送更新列表的情况下,而不是客户端发送必要步骤来重新创建更新列表的情况下。但是,您可能应该提交该评论作为答案。

标签: mongodb sorting


【解决方案1】:

在不知道的情况下很难说哪个选项更好:

  1. 排序顺序通常多久更新一次
  2. 您将针对文档运行哪些查询以及多久进行一次
  3. 一次可以排序多少个文档

我相信你会做更多的查询而不是更新,所以我个人会选择第一个选项。它很容易实现,也很简单,这意味着它会被拒绝。我了解您对更新多个文档的担忧,但更新将就地完成,我的意思是不会发生文档移动,因为您实际上并未更改文档大小。只需创建一个简单的测试。生成 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 移到顶部时失败。当我们只更新了两个文档时会发生故障,因此我们将得出以下状态,因为我们只设法更新了 ids 2 和 1:

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

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

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

希望对你有帮助!

【讨论】:

  • 我肯定会有比更新更多的查询。我对多文档更新的担忧不是它们可能需要很长时间,而是某些地方可能会出错,只要您自己不实现事务行为,这可能会给您留下损坏的数据。但是,对于基于文档的数据建模,通常有一个不错的解决方案,如果没有该领域的丰富经验,您可能不会想到。这就是我问的原因。
  • 实际上我遇到了同样的问题,只是想分享我从中学到的东西,我找不到或想出更好的解决方案,如果有人提出更好的解决方案,我会很高兴这里。关于一致性问题,您在这里是绝对正确的,但就我而言,这并不重要。这不太可能发生,即使发生也不会破坏数据。但对于您的解决方案来说,这可能是至关重要的。抱歉,我不会为第一个选项感到不安,它对我来说还不够清楚,一致性在这里很重要。
  • 好吧,如果更新排序值时出现问题,您很可能会多次使用相同的排序值,这至少会导致两个元素的排序顺序未定义.这是否会成为一个问题取决于用户的期望以及应用程序处理这种情况的能力。至少它会导致不一致,这几乎总是某种坏事。我认为最好的办法是尽可能避免多文档更新。但我还没有投入生产,所以这在某种程度上是假设性的。
  • 查看我的更新,我试图描述为什么在 mu 情况下它不是问题
  • 感谢您的澄清。说得通。您实际上使您的应用程序能够处理这种状态。尽管如此,我还是喜欢另一种方法,因为它消除了对多文档更新的需要。但是,根据存储在父级中的顺序对实际实体进行排序将需要更多工作。也许我们会很幸运,仍然有人会采用另一种方法。
猜你喜欢
  • 1970-01-01
  • 2021-09-19
  • 2023-03-08
  • 1970-01-01
  • 2015-05-12
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多