我有一个巨大的数据集,我正在使用 Mongoose 模式,每个数据元素看起来像这样:
{
field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”:
field2: “GAA…..GAATG”
}
来源:Reading an FASTA file
如您所见,单个元素简单而小,但数量巨大!它们加起来将超过 200MB。
问题是:我无法将它保存到 mongo,因为它太大(> 200MB) .
尽管如此,我还是找到了 GridF,
在最简单的场景中:如何使用 GridFS 或任何类似的解决方案来保存 JSON 文件,就像我使用小型 JSON 文件一样。与其他方法相比,这种方法有哪些优点和缺点(如果有的话)?你认为我的方法有效吗?我的意思是,我在这里提到的那个,使用 JSON 文件树和
populate
后来,它工作!作为使用 mongoose 保存 JSON 文件的示例:
Model.create([
{
field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”:
field2: “GAA…..GAATG”
},
{
field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”:
field2: “GAA…..GAATG”
}]);
在这里,我刚刚保存了一个包含两个元素的 JSON 文件,我不能用一个巨大的文件来做到这一点,我需要分成更小的部分(比如 1% 的 block ),并创建刚才提到的树,至少这是我的解决方案。
恐怕我正在重新发明轮子。我可以独立保存这些文件,它可以工作,但我需要保持它们的相关性,因为它们属于同一个文件,就像图像的较小块属于同一个图像一样。
恐怕我正在重新发明轮子。
当前解决方案
这是我目前的解决方案,使用我自己的见解!看到我在这里提到只是出于好奇,它不使用 GridFS,因此,我仍然愿意接受使用 GridFS 的建议。它只使用 JSON 文件,并将文档分成更小的文件,就像层次结构一样。它是一棵树,我只想要溶液中的叶子。
我已经解决了问题尽管如此,出于学习目的,使用此图,我想看看是否可以使用 GridFS 来做同样的事情。
讨论
我的第一种方法是将它们保留为 subdoc:它失败了!然后我试图只保留他们的 id,他们的 id 对应于整个 block 的 35%,并且大于 16MB:失败!然后我决定创建一个虚拟文档,只是为了保留 id,并只存储虚拟文档的 id:成功!
最佳答案
很可能不值得使用 GridFS 将数据存储在 Mongo 中。
二进制数据从不真正属于数据库,但如果数据很小,将其放入数据库(查询能力)的好处大于缺点(服务器负载,速度慢)。
在这种情况下,您似乎希望将文档数据 (JSON) 存储在 GridFS 中。您可以这样做,并以存储任何其他二进制数据的方式存储它。然而,数据将是不透明的。您不能查询存储在 GridFS 文档中的 JSON 数据,只能查询文件元数据。
查询大数据
正如您提到的要查询数据,您应该检查数据的格式。如果您的数据采用示例中列出的格式,那么似乎不需要复杂的查询,只需要字符串匹配。所以有几种选择。
案例一:大数据,少点
如果您的数据集不多(field1
和 field2
对),但每个数据集都很大(field2
包含许多字节),请将它们存储在其他地方并仅存储对其的引用。一个简单的解决方案是将数据(以前的 field2
)存储在 Amazon S3 上的文本文件中,然后存储然后存储链接。例如
{
field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”,
field2link: "https://my-bucket.s3.us-west-2.amazonaws.com/puppy.png"
}
案例二:小数据,多点
如果您的每个数据集都很小(小于 16 MB)但有很多数据集,请将您的数据存储在 MongoDB(没有 GridFS)中。
细节
在您的情况下,数据非常大,不建议使用 GridFS 存储它。
This answer为底部提供了基准。基准似乎表明检索时间或多或少与文件大小成正比。使用相同的设置,从数据库中检索文档需要 80 秒。
可能的优化
GridFS 中的默认 block 大小为 255 KiB。您可以通过将 block 大小增加到最大值 (16 MB) 来减少大文件访问时间。如果 block 大小是唯一的瓶颈,那么使用 16 MB block 大小会将检索时间从 80 秒减少到 1.3 秒 (80/(16MB/255KiB) = 1.3)。您可以在初始化 GridFS 存储桶时执行此操作。
new GridFSBucket(db, {chunkSizeBytes: 16000000})
更好的策略是将唯一的文件名存储在 Mongo 中,然后从文件系统中检索文件。
其他缺点
在 Mongo 中存储二进制数据的另一个可能的缺点来自 this site :
“如果二进制数据很大,那么将二进制数据加载到内存中可能会导致频繁访问的文本(结构化数据)文档被挤出内存,或者更一般地说,工作集可能无法放入 RAM。这会对数据库的性能。” [ 1 ]
例子
在 GridFS 中保存文件,改编自 Mongo GridFS tutorial
const uri = 'mongodb://localhost:27017/test';
mongodb.MongoClient.connect(uri, (error, db) => {
const bucket = new mongodb.GridFSBucket(db);
fs.createReadStream('./fasta-data.json')
.pipe(bucket.openUploadStream('fasta-data.json'))
.on('finish', () => console.log('done!'))
;
});
关于javascript - 如何使用 GridFs 保存 JSON 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60968353/