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 请求。
- 更好的东西?
我的架构是否正确? 存储传感器数据的各个文档,然后通过 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 编写的内置化简器低很多倍。