文档菜单
文档首页
/
MongoDB 手册
/ / /

模型IOT数据

本页内容

  • 桶模式
  • MongoDB中的时间表示
  • 示例

物联网(IoT)是一个连接到互联网的物理对象网络。许多这些设备,如传感器,会生成数据。

为了有效地存储和检索这些数据,您可以使用桶模式。

将物联网数据组织起来的一种常见方法是将数据分组到桶中。桶化将特定的数据分组组织起来,以帮助

  • 发现历史趋势,

  • 预测未来趋势,以及

  • 优化存储使用。

常用的分组数据参数包括

  • 时间

  • 数据源(如果您有多个数据集)

  • 客户

  • 数据类型(例如,财务数据中的交易类型)

注意

从MongoDB 5.0开始,时序集合是推荐用于时序数据的集合类型。请勿与时序集合一起使用桶模式,因为这可能会降低性能。

考虑一个存储从传感器获取的温度数据的集合。该传感器每分钟记录一次温度并将数据存储在一个名为temperatures:

// temperatures collection
{
"_id": 1,
"sensor_id": 12345,
"timestamp": ISODate("2019-01-31T10:00:00.000Z"),
"temperature": 40
}
{
"_id": 2,
"sensor_id": 12345,
"timestamp": ISODate("2019-01-31T10:01:00.000Z"),
"temperature": 40
}
{
"_id": 3,
"sensor_id": 12345,
"timestamp": ISODate("2019-01-31T10:02:00.000Z"),
"temperature": 41
}
...

的集合中。这种方法在数据和索引大小方面扩展性不好。例如,如果应用程序需要在sensor_idtimestamp字段上创建索引,则需要对传感器的每个传入读数进行索引以提高性能。

您可以使用文档模型将数据桶化到包含特定时间段测量的文档中。考虑以下更新的模式,它将每分钟的读数桶化到每小时的组中

{
"_id": 1,
"sensor_id": 12345,
"start_date": ISODate("2019-01-31T10:00:00.000Z"),
"end_date": ISODate("2019-01-31T10:59:59.000Z"),
"measurements": [
{
"timestamp": ISODate("2019-01-31T10:00:00.000Z"),
"temperature": 40
},
{
"timestamp": ISODate("2019-01-31T10:01:00.000Z"),
"temperature": 40
},
...
{
"timestamp": ISODate("2019-01-31T10:42:00.000Z"),
"temperature": 42
}
],
"transaction_count": 42,
"sum_temperature": 1783
}

此更新的模式提高了可扩展性,并反映了应用程序实际使用数据的方式。用户很可能不会查询特定的温度读数。相反,用户可能会查询一小时或一天的温度行为。桶模式通过将数据分组到统一的时间段来帮助实现这些查询。

示例文档 包含两个计算字段:transaction_countsum_temperature。如果应用程序频繁需要检索特定小时的温度总和,计算累积的总和可以帮助节省应用程序资源。这种计算模式方法可以消除每次请求数据时都计算总和的需求。

预聚合的 sum_temperaturetransaction_count 值允许进行进一步的计算,例如特定桶的平均温度(sum_temperature / transaction_count)。用户更有可能查询应用程序在下午2:00至3:00之间的平均温度,而不是查询下午2:03的具体温度。桶化和预计算某些值使应用程序更容易提供此类信息。

MongoDB 默认以 UTC 存储时间,并将任何本地时间表示转换为这种形式。必须操作或报告某些未修改的本地时间值的应用程序可能将时区与 UTC 时间戳一起存储,并在其应用程序逻辑中计算原始的本地时间。

在MongoDB shell中,您可以存储当前日期和客户端相对于UTC的偏移量。

var now = new Date();
db.data.insertOne( { date: now,
offset: now.getTimezoneOffset() } );

通过应用保存的偏移量可以重构原始本地时间

var record = db.data.findOne();
var localNow = new Date( record.date.getTime() - ( record.offset * 60000 ) );

返回

原子操作