如何在不使用 GridFS 的情况下在 MongoDB 中存储大型 JSON 文档(>20MB)
How to store large JSON documents(>20MB) in MongoDB without using GridFS
我想在 MongoDB 中存储一个大文档,但是,这是我与文档交互的两种方式:
- 我经常读取该数据并需要使用聚合来获取该数据的一部分
- 当我需要写入文档时,我将再次从头开始构建它,即删除现有文档并插入一个新文档。
示例文档如下所示:
{
"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。
我想到的解决方案:
- 我想以 gridfs 格式存储 json 数据并按照此处的文档读取它:https://docs.mongodb.com/manual/core/gridfs/。但是,每次我只想在大型 json blob 中查找一个对象时,我都需要读取整个文件,而且我需要经常在多个大型文档上进行此类读取,这会导致高内存用法
- 我想到将 json 拆分成多个部分并将每个对象存储在它自己的单独集合中,当我需要获取整个文档时,我可以重新组合 json
我该如何解决这个问题?有什么明显的东西是我在这里遗漏的吗?
我认为你的问题是你没有使用正确的工具来完成工作,或者没有按照它们应有的方式使用你拥有的工具。
如果您想将大对象持久化为 JSON,那么我认为数据库不是一个自然的选择——尤其是在对象很大的情况下。我会研究设计用于很好地完成此任务的存储系统(假设您的解决方案是否在 Azure/AWS/GCP 上,看看他们提供什么专业服务)或者如果您 运行 在本地服务器上,甚至只是文件系统。
没有理由不能在文件中包含 JSON 并在数据库中包含相关数据 - 是的,这存在问题,但 MongoDB 的限制不会是一个其中
I do frequent reads of that data and need to get a part of that data using aggregations
如果您经常读取,并且只读取部分数据,那么强制您的系统始终读取整个记录意味着您只是在惩罚自己。一种选择是以不会导致完整读取的性能损失的方式存储高度读取的位。
将对象存储为JSON意味着您可以更改您的程序和数据,而不必担心数据库的外观,这很方便。但它也有它的局限性。如果您认为自己已经达到了这些限制,那么现在可能是考虑重新架构的时候了。
I thought of splitting the JSON into parts and storing each object in it's own separate collection, and when I need to fetch the entire document, I can reassemble the JSON
这绝对值得研究。您只需要确保不同的部分不存储在相同的 table / 行中,否则不会有任何改进。仔细想想你是如何把对象溢出来的——想想对象处理的关键场景——例如你提到阅读。设计子对象以与关键场景保持一致是可行的方法。
例如,如果您通常在对象摘要列表(例如搜索结果)中显示对象的摘要,则摘要文本、对象名称、id 是您要拆分的对象数据的候选对象。
我想在 MongoDB 中存储一个大文档,但是,这是我与文档交互的两种方式:
- 我经常读取该数据并需要使用聚合来获取该数据的一部分
- 当我需要写入文档时,我将再次从头开始构建它,即删除现有文档并插入一个新文档。
示例文档如下所示:
{
"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。
我想到的解决方案:
- 我想以 gridfs 格式存储 json 数据并按照此处的文档读取它:https://docs.mongodb.com/manual/core/gridfs/。但是,每次我只想在大型 json blob 中查找一个对象时,我都需要读取整个文件,而且我需要经常在多个大型文档上进行此类读取,这会导致高内存用法
- 我想到将 json 拆分成多个部分并将每个对象存储在它自己的单独集合中,当我需要获取整个文档时,我可以重新组合 json
我该如何解决这个问题?有什么明显的东西是我在这里遗漏的吗?
我认为你的问题是你没有使用正确的工具来完成工作,或者没有按照它们应有的方式使用你拥有的工具。
如果您想将大对象持久化为 JSON,那么我认为数据库不是一个自然的选择——尤其是在对象很大的情况下。我会研究设计用于很好地完成此任务的存储系统(假设您的解决方案是否在 Azure/AWS/GCP 上,看看他们提供什么专业服务)或者如果您 运行 在本地服务器上,甚至只是文件系统。
没有理由不能在文件中包含 JSON 并在数据库中包含相关数据 - 是的,这存在问题,但 MongoDB 的限制不会是一个其中
I do frequent reads of that data and need to get a part of that data using aggregations
如果您经常读取,并且只读取部分数据,那么强制您的系统始终读取整个记录意味着您只是在惩罚自己。一种选择是以不会导致完整读取的性能损失的方式存储高度读取的位。
将对象存储为JSON意味着您可以更改您的程序和数据,而不必担心数据库的外观,这很方便。但它也有它的局限性。如果您认为自己已经达到了这些限制,那么现在可能是考虑重新架构的时候了。
I thought of splitting the JSON into parts and storing each object in it's own separate collection, and when I need to fetch the entire document, I can reassemble the JSON
这绝对值得研究。您只需要确保不同的部分不存储在相同的 table / 行中,否则不会有任何改进。仔细想想你是如何把对象溢出来的——想想对象处理的关键场景——例如你提到阅读。设计子对象以与关键场景保持一致是可行的方法。
例如,如果您通常在对象摘要列表(例如搜索结果)中显示对象的摘要,则摘要文本、对象名称、id 是您要拆分的对象数据的候选对象。