在mongo中存储大文件(但不是媒体)的正确方法?

时间:2011-12-10 19:35:32

标签: c++ mongodb gridfs

我知道在Mongo世界中大数据,如图像,音乐和视频进入GridFS,小型和结构数据直接传递给Mongo。

最近,我超出了BSONObj大小的限制。我的文件,实际上是对象,如vector<vector<vector<Foo>>>看起来像一个小的常规数据(具有嵌套结构),但具有巨大的大小(从20Mb开始)。我不确定,但是通过事先转换为bytearray将它们写入GridFS似乎是一个坏主意(向量具有动态,非常量长度)。有一些解决方法吗?

Optionaly,我想对这些对象执行查询,例如从顶层向量中获取第一个切片(索引)。

1 个答案:

答案 0 :(得分:1)

根据您要支持的查询,我想到了两种选择。但是,我相信对于几百MB的数据大小,这些比在RAM中做所有事情并使用MongoDB作为一个blob商店要慢:

1)您可以将每个维度放在一个单独的对象中:

FirstLevel {
   "_id" : ObjectId("..."),
   "Children" : [ ObjectId("..."), ... ]
   // list of vector ids (of the second level)
}

可能不是一个很好的解决方案。它仍然对你可以存储的项目数量施加限制,但数量应该非常大,因为它大约是(16M / id size)^3,如果Foo是一个大对象,可能要小得多(在叶子中)。

访问将非常缓慢,因为你必须走树。节点和叶子有一些不同的数据格式。但是,它是非常可扩展的(任何维度)。

2)由于您的数据是三维的,您可以将其存储为“真正的三维”:

Data {
  Coords : { "x" : 121, "y" : 991, "z" : 12 },
  ActualData : { /* Serialized Foo */ }
}

{x, y, z}元组上使用复合索引,这非常有效地支持维度切片,除了“select all z = 13之类的操作,然后按x排序”。这种方法带来了相当多的开销,你可能需要一个自定义(de)序列化器。我不知道C ++驱动程序,但在C#中很容易实现。

这也将很好地支持锯齿状阵列。

2a)如果你不想要2)的开销,你可以将坐标压缩成一个long。这类似于geohashing,这是MongoDB为其地理空间索引所做的。

然后查询坐标切片是一个位掩码操作,遗憾的是,查询不支持这种操作($bit仅适用于更新)。不过你可以vote for it

也许你也可以为你的目的滥用geohashing,但那是相当实验性的。