在MongoDB的多个列表中维护项目位置的模式性能更好吗?

insrf1ej  于 2023-03-01  发布在  Go
关注(0)|答案(1)|浏览(111)

我有两个集合,listsitems,每个项都可以属于任意数量的列表,并且每个列表都有一个自定义位置。为了避免过度架构,哪一个性能更好?为什么?

答:维护列表数组及其在每个项目文档中的位置,如下所示:

/* item schema */
{
  _id: ObjectID, // itemID
  lists: [
    {
      _id: ObjectID, // the listID
      orderNr: Number, // the position in that specific list
    }
  ]
}

B:维护一个额外的集合contexts,该集合将按照itemID在任何给定列表中出现的顺序存储itemID数组:

/* context schema */
{
    _id: ObjectID,
    listID: ObjectID,
    items: [
        {
            _id: ObjectID, // itemID
            orderNr: Number // position of item in the list
        }
    ]
}

我个人的理解是B是更好的选择,因为您可以通过_id字段查询列表的上下文文档,从items数组的开头获取一些ID,然后通过它们的_id字段直接查询这些项。
而在版本A中,如果我想象有5,000个项,每个项存在于3-4个不同的列表中,并且每个项都改变了位置,那么Mongo要根据每个项中的数组中的值找到所有这些项似乎要做很多工作(我知道Mongo需要搜索和比较所有项目,而不是只按_id查询有限数量的项目,能够在找到last _id项的时刻停止)。
但也许MongoDB的内部工作方式中有一些我不知道的东西并没有让选项A成为问题?这肯定意味着维护工作量大大减少。或者也许还有第三种方法我没有看到?

wgeznvg7

wgeznvg71#

我认为,选项A对于模式上下文是更好的选择。
但这两个都需要使用查询aggregation,即使会有额外的集合。问题是,我们需要提高性能,
以下是一些生产步骤,

  • 当使用$lookup时,使用ObjectId之类的索引来联接集合,ref:https://www.mongodb.com/docs/manual/core/aggregation-pipeline-optimization/#std-label-aggregation-pipeline-optimization-indexes-and-filters
  • 过滤$lookup操作的输出,在内部使用pipeline
  • 我使用分页方法,所以我们不必担心是否有很多数据

有很多工具可以生成分页数据,我建议使用使用mongodb本地驱动器的工具
这里是一个生成分页示例工具,它只需要一次查询就可以生成分页数据,且能够执行多次连接(查找)
mongodb-pagination

相关问题