对于16mb以上大小的文档,MongoDB的解决方法是什么?

时间:2016-10-21 11:19:47

标签: mongodb

我正在研究的MongoDB集合从手机中获取传感器数据,并且每隔2-6秒就会被发送到服务器。

数据量很大,4-5小时后超过16mb的限制,似乎没有任何解决方法吗?

我试过在Stack Overflow上搜索它并经历了各种问题,但没有人真正分享他们的黑客。

有没有办法...在数据库方面可能会分发块,就像通过gridFS对大文件一样?

2 个答案:

答案 0 :(得分:13)

要解决此问题,您需要对数据结构进行一些小修改。通过它的声音,对于您的文档超过16mb的限制,您必须将传感器数据嵌入到单个文档中的数组中。

我不建议在这里使用GridFS,我不相信它是最好的解决方案,这就是为什么。

您可以使用一种称为bucketing的技术,它将您的传感器读数基本上分成单独的文档,为您解决此问题。

它的工作方式是:

假设我有一个文档,其中包含一些特定传感器的嵌入式读数,如下所示:

{
    _id : ObjectId("xxx"),
    sensor : "SensorName1",
    readings : [
        { date : ISODate("..."), reading : "xxx" },
        { date : ISODate("..."), reading : "xxx" },
        { date : ISODate("..."), reading : "xxx" }
    ]
}

通过上述结构,已经存在一个重大缺陷,读数数组可能呈指数级增长,超过16mb的文档限制。

所以我们可以做的是稍微改变结构看起来像这样,包括一个count属性:

{
    _id : ObjectId("xxx"),
    sensor : "SensorName1",
    readings : [
        { date : ISODate("..."), reading : "xxx" },
        { date : ISODate("..."), reading : "xxx" },
        { date : ISODate("..."), reading : "xxx" }
    ],
    count : 3
}

这背后的想法是,当你将读数推入嵌入式数组时,为每次执行的推送增加($ inc)计数变量。当你执行这个更新(推送)操作时,你会在这个" count"上包含一个过滤器。属性,可能看起来像这样:

{ count : { $lt : 500} }

然后,设置更新选项,以便设置" upsert" to" true":

db.sensorReadings.update(
    { name: "SensorName1", count { $lt : 500} },
    {
        //Your update. $push your reading and $inc your count
        $push: { readings: [ReadingDocumentToPush] }, 
        $inc: { count: 1 }
    },
    { upsert: true }
)

有关MongoDb Update和Upsert选项的更多信息,请参阅此处:

MongoDB update documentation

当不满足过滤条件时(即,当此传感器没有现有文档,或者计数大于或等于500时)将会发生什么 - 因为每次按下项目时都会递增它,将创建一个新文档,现在将读数嵌入此新文档中。因此,如果你这样做,你永远不会达到16mb的限制。

现在,当查询数据库以获取特定传感器的读数时,您可能会返回该传感器的多个文档(而不是仅包含其中所有读数的文档),例如,如果您有10,000个读数,您将获得返回20份文件,每份都有500个读数。

然后,您可以使用聚合管道和$ unwind来过滤您的读数,就像它们是他们自己的个人文档一样。

有关展开的更多信息,请参阅此处,它非常有用

MongoDB Unwind

我希望这会有所帮助。

答案 1 :(得分:0)

您可以使用MongoDB中的GridFS来处理此类情况。

  

GridFS不是将文件存储在单个文档中,而是将文件分成多个部分或块1,并将每个块存储为单独的文档。默认情况下,GridFS使用255 kB的块大小;也就是说,GridFS将文件分成255 kB的块,但最后一个块除外。最后一个块只有必要的大小。同样,不大于块大小的文件只有最终的块,只需要使用所需的空间和一些额外的元数据。

GriFS的文档几乎包含了实现GridFS所需的一切。你可以关注它。

由于您的数据是流式,您可以尝试以下内容...

gs.write(data, callback)
  

其中data是Buffer或string,callback获取两个参数 - 一个错误对象(如果发生错误)和结果值,指示写入是否成功。 GridStore未关闭时,每次写入都会附加到打开的GridStore。

您可以按此github page来获取与流媒体相关的信息。