我在mongodb中有以下时间序列数据
频道收集包含有关每个频道的数据。 每个频道文档都有实时数据 - > rtData是一个json数组,用于保存该通道的时间序列数据。
db.channels.find({})。pretty()给出了类似的结构
{
channelName:"ABC",
rtData:[
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
.
.
.
},
{
channelName:"NBC",
rtData:[
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
{
ts:ISO_DATE(timestamp),
data:[12, 14]
},
.
.
.
},
现在,我每4秒钟获得一个或多个频道的更新记录
{
ts: ISO_DATE(timestamp),
data: [14,15]
}
我需要在该频道的rtData数组中推送/更新此记录。
所以我所做的与此类似 -
channels.findOne({query}, function(channel) {
channel.rtData.push(newData);
channels.findAndModify({query}, {$set:{rtData: channel.rtData}},
function({}))
})
找到频道,将数据推送到rtData数组并进行查找和修改。
现在,当数据量很低时,这似乎有效。但是当一个单一通道的rtData数组中有近50K元素时,应用程序无法处理。
是否有效更新时间序列数据。
答案 0 :(得分:1)
你已经过了你的模型,imho。请记住,MongoDB中的BSON文档有16MB的大小限制。 此外,修改文档比简单地插入文档需要花费更多的时间。
由于ObjectID contains a timestamp already并且还为每个输入的值提供了唯一性,例如
{
_id: new ObjectID(),
channelName: "NBC",
value: [14,15]
}
使插入数据非常有效。对于基于日期的查询,您可以利用ObjectIDs以包含自纪元以来的秒数的4字节值的十六进制表示开始,并且以其他方式单调增加:
secs = Math.floor(Date.Now()/1000)
hexSecs = secs.toString(16)
id = ObjectId(hexSecs+"0000000000000000")
db.values.find({"_id":{$lt:id}})
此示例将为您提供所有早于调用时间Date.Now()
的条目。当然,您可以使用转换开始日期和结束日期的相同方法查询范围。有关更详细的说明,请参阅the according entry "Popping time stamps into ObjectIds" on Kristina Chodorow's blog
其余的查询和聚合应该是显而易见的。