我正在研究的MongoDB集合从手机中获取传感器数据,并且每隔2-6秒就会被发送到服务器。
数据量很大,4-5小时后超过16mb的限制,似乎没有任何解决方法吗?
我试过在Stack Overflow上搜索它并经历了各种问题,但没有人真正分享他们的黑客。
有没有办法...在数据库方面可能会分发块,就像通过gridFS对大文件一样?
答案 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选项的更多信息,请参阅此处:
当不满足过滤条件时(即,当此传感器没有现有文档,或者计数大于或等于500时)将会发生什么 - 因为每次按下项目时都会递增它,将创建一个新文档,现在将读数嵌入此新文档中。因此,如果你这样做,你永远不会达到16mb的限制。
现在,当查询数据库以获取特定传感器的读数时,您可能会返回该传感器的多个文档(而不是仅包含其中所有读数的文档),例如,如果您有10,000个读数,您将获得返回20份文件,每份都有500个读数。
然后,您可以使用聚合管道和$ 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来获取与流媒体相关的信息。