首页 > 解决方案 > 如何在不使用 GridFS 的情况下在 MongoDB 中存储大型 JSON 文档(>20MB)

问题描述

我想在 MongoDB 中存储一个大文档,但是,这是我将与文档交互的两种方式:

  1. 我经常读取该数据并且需要使用聚合来获取该数据的一部分
  2. 当我需要写入文档时,我将再次从头开始构建它,即删除存在的文档并插入一个新文档。

以下是示例文档的外观:

{
    "objects_1": [
        {
        
        }
    ],
    "objects_2": [
        {
        
        }
    ],
    "objects_3": [
        {
        
        }
    ],
    "policy_1": [
        {
        
        }
    ],
    "policy_2": [
        {
        
        }
    ],
    "policy_3": [
        {
        
        }
    ]
}

这是我想要访问该数据的方式:

{
"objects_1": [
        {

        }
}

如果我以传统方式存储它,我会编写如下查询:

db.getCollection('configuration').aggregate([
    { $match: { _id: "FAAAAAAAAAAAA" } },
    { $project: {
        "_id": 0,
        "a_objects": {
            $filter: {
                input: "$settings.a_objects",
                as: "arrayItem",
                cond: { $eq: [ "$$arrayItem.name", "objectName" ] }
            }
        }
    }}
])

但是,由于文档的大小 >16 MB,我们无法将其直接保存到 MongoDB。大小最大为 50MB。

我想到的解决方案:

  1. 我想以 gridfs 格式存储 json 数据并按照此处的文档阅读它:https ://docs.mongodb.com/manual/core/gridfs/ 。但是,每次我只想在大型 json blob 中查找一个对象时,我都需要读取整个文件,并且我需要经常对多个大型文档进行此类读取,这会导致高内存使用
  2. 我想将 json 拆分为多个部分并将每个对象存储在它自己的单独集合中,当我需要获取整个文档时,我可以重新组装 json

我应该如何解决这个问题?我在这里有什么明显的遗漏吗?

标签: jsonmongodbarchitecture

解决方案


我认为你的问题是你没有使用正确的工具来完成这项工作,或者没有按照它们本来应该使用的方式使用你拥有的工具。

如果您想将大对象保存为 JSON,那么我认为数据库不是一个自然的选择——尤其是在对象很大的情况下。我会考虑设计用来做得很好的存储系统(比如,如果您的解决方案在 Azure/AWS/GCP 上,请查看他们提供的专业服务),或者如果您在本地服务器上运行,甚至只是文件系统。

没有理由不能将 JSON 放在文件中,而将相关数据放在数据库中 - 是的,这存在一些问题,但 MongoDB 的局限性不会是其中之一。

我经常读取该数据并且需要使用聚合来获取该数据的一部分

如果您经常读取,并且只读取部分数据,那么强制您的系统始终读取整个记录意味着您只是在惩罚自己。一种选择是以不会导致完全读取的性能损失的方式存储高度读取的位。

将对象存储为 JSON 意味着您可以更改程序和数据,而不必担心数据库的外观,它很方便。但它也有它的局限性。如果你认为你已经达到了这些限制,那么现在可能是考虑重新架构的时候了。

我想将 JSON 拆分为多个部分并将每个对象存储在它自己的单独集合中,当我需要获取整个文档时,我可以重新组装 JSON

这绝对值得研究。您只需要确保不同的部分没有存储在同一个表/行中,否则不会有任何改进。仔细想想你是如何将对象溢出的——想想对象处理的关键场景——例如你提到读取。设计子对象以与关键场景保持一致是要走的路。

例如,如果您通常在对象摘要列表(例如搜索结果)中显示对象的摘要,则摘要文本、对象名称、ID 是您将拆分的对象数据的候选对象。


推荐阅读