从每个节点(Cloudant/couchdb)获取数据库的最后N个数据点



TL;DR:MapReduce还是POST请求?

从 Cloudant 或等效数据库中获取多个传感器的最新 n 个数据点的正确(=最有效)方法是什么?

传感器数据存储在单独的文档中,如下所示:

{
"_id": "2d26dbd8e655ae02bdab611afc92b6cf",
"_rev": "1-a64448521f05935b915e4bee12328e84",
"date": "2017-06-20T15:59:50.509Z",
"name": "Sensor01",
"temperature": 24.5,
"humidity": 45.3,
"rssi": -33
}

我想从 sensor01-sensor99 获取最新的 10 个文档,以便我可以将其提供给 UI。

我发现了几个选择:

1.使用地图缩减功能

将每个传感器数据减少到传感器01、传感器02等下的数组中。

例如 地图:

function (doc) {
if (doc.name && doc.temperature) emit(doc.name, doc.temperature);
}

减少:

function (keys, values, rereduce) {
var temp_arr=[];
for (i=0;i<values.length;i++)
{
temp_arr.push(values);
}
return temp_arr;
}

我无法让这个工作,但我认为这种方法应该是可行的。

2. 多文档获取

{
"queries":[
{sensor01},{sensor02},{sensor03} etc....
]};

每个 {sensor0x} 的过滤方式

{"startkey": [sensors[i],{}],"endkey": [sensors[i]],"limit": 5}

这样我可以使用 ?降序=true 来订购文档 我实现了它并且它有效。如果我有 1000 个传感器,每个传感器有 10000 个数据点,我怀疑我是否应该使用它。 对于数百个传感器,我需要发送一个非常大的 POST 请求。

  1. 更好的东西?

我的架构是否正确? 存储传感器数据的各个文档,然后通过 REST API 获取所有数据来填充 UI。

谢谢!

每个文档存储一个读数的方法没有错,但是没有真正有效的方法来获取多个传感器的"最后n个数据点"。

我们可以创建一个MapReduce函数:

function (doc) {
if (doc.name && doc.temperature && doc.date) {
emit([doc.name, doc.date], doc.temperature);
}
}

这将创建按name和日期排序的索引。

我们可以通过查询视图来访问单个传感器的最新读数:

/_design/mydesigndoc/_view/myview?startkey=["Sensor01","2020-01-01"]&descending=true&limit=10

这将以最新的第一顺序获取"Sensor01"的读数:

  • startkey 和 endkey 在执行降序时受到尊敬=true
  • 降序=真的意思是崇敬的顺序
  • 限制 - 所需的读数数(或您的说法中的 N)

这是对Cloudant/CouchDB的一种非常有效的使用,但它只返回单个传感器的最后n个读数。要检索其他传感器的数据,需要额外的 API 调用。

创建如下索引:

function (doc) {
if (doc.name && doc.temperature && doc.date) {
emit(doc.date, doc.temperature);
}
}

按日期对每个读数进行排序。然后,您可以使用以下命令检索最新的 n 个读数:

/_design/mydesigndoc/_view/myview?startkey="2020-01-01"&descending=true&limit=200

如果您的所有传感器都以相同的速率保存数据,那么只需使用更大的限制就可以获得所有传感器的最新读数。

这也是CouchDB/Cloudant的有效使用。

您可能还想查看内置的化简器(_count、_sum 和 _stats),以使数据库为您汇总读数。它们是创建 IoT 数据的年/月/日分组的好方法。

一般来说,我建议不要使用自定义化简器,它们的效率比用 Erlang 编写的内置化简器低很多倍。

最新更新