我一直试图解决这个问题一段时间,阅读大量的SO问题并浏览文档,但无济于事。我希望有人能指出我正确的方向!
考虑以下文件:
{
"_id": "045bdeb40176b33cf07b21cd1fb3949e",
"type": "test_result",
"customer_id": "customer",
"product_id": "product1",
"type_id": "type",
"version_id": "1.0.0",
"timestamp": 1381505909000,
"test_result": "passed",
"serial_nr": "NEP000001"
}
{
"_id": "045bdeb40176b33cf07b21cd1fb3c434",
"type": "measurement_result",
"test_result_id": "045bdeb40176b33cf07b21cd1fb3949e",
"measurement_id": "customer:product1:type:1.0.0:0",
"timestamp": 1381505909000,
"data": 2.5
}
应用程序包含以不同方式测量的单位数据。每次测试单元时都会插入一个test_result
文档。每个单元都有一个唯一的serial_nr
。为在单元上进行的每次测量插入一个measurement_result
文档(通常每单位约50次测量)。该单元的每个度量都有一个唯一的measurement_id
。插入结果后,将生成timestamp
。一个单元可以多次进行测试。
我正在尝试构建的视图如下:
measurement_id
的所有度量,但仅针对最早的结果。如果任何一个单元已经过多次测试,则只应包括第一次测试的测量结果。 measurement_id
的所有度量,但仅针对最新结果(与最早结果相同的规则)。目标是缩小data
字段以计算average
,min
,max
和standard deviation
等统计信息,这是非常有价值的能够在测试一个单元的第一个/最晚时间之间分离统计数据。
我一直在尝试使用复杂的密钥,非常先进的减少和许多其他方法,但我似乎无法隔离最新/最新的结果。
这个应用程序仍然没有生产,所以任何解决方案都是受欢迎的(我猜甚至切换数据库系统)。我应该以任何其他方式构建数据吗?这甚至可能吗?从长远来看,我将拥有大量数据,因此我可以逐步计算统计数据非常重要。
This question似乎与我的相同或更不一样,但从来没有任何答案,我已经达到了他的目标。
更新#1
对于#1和#2的情况,我可能只需按[serial_nr, timestamp]
映射,然后关闭reduce_limit以允许我只返回最近的条目。我不知道从长远来看这会如何影响性能呢?
对于#3和#4来说,它更难。由于我需要按measurement_id
分组计算,因此它需要是密钥数组中的第一个元素。那么呢?
(为了简单起见,我现在假设measurement_result
文件也有serial_nr
)
map:
function(doc) {
if (doc.type == 'measurement_result')
emit([doc.measurement_id, doc.serial_nr, doc.timestamp], doc.data)
}
reduce:
_stats
带GET
的{p> group_level=1
是我唯一的选择,因为否则我会为每个measurement_id获得单独的结果 - 但我仍然无法过滤掉最新或最旧的结果,这只是把我所有人都拿走了。现在我也许可以写一个reduce函数以某种方式检查重复serial_nr
并且只返回最新/最旧的,但我无法弄清楚如何。
希望这可以解决一下这个问题。
答案 0 :(得分:3)
我认为您可能犯的一个错误是尝试以RDBMS方式组织数据。如果您的测量结果只是大约50左右,那么他们可以很容易地生活在同一个文档中。如果没有上限的上限,你只需要担心....我在同一个文档中有数千个,我不推荐。
使用couchdb的update handlers你可以创建一个可以按顺序向数组添加值的函数....这里是一个快速参考
基本上你的更新处理程序必须创建doc(如果它不存在)并向数组添加条目。 使用您的示例,您可以将测量和测试结果作为简单的自然键。 你的新文档应该是这样的:
{
"_id": "NEP000001-measurements",
"type": "measurement_result",
"test_result_id": "045bdeb40176b33cf07b21cd1fb3949e",
"serial_nr": "NEP000001",
"measurements": [
{
"measurement_id": "customer:product1:type:1.0.0:0",
"timestamp": 1381505909000,
"test_result_id": "045bdeb40176b33cf07b21cd1fb3949e",
"data": 2.5
},
{
"measurement_id": "customer1:product2:type:1.0.0:0",
"timestamp": 1381505909005,
"test_result_id": "045bdeb40176b33cf07b21cd1fb3949e",
"data": 2.7
}
]
}
Couchdb视图允许您将视图中最终的内容与数据库中的数据进行分割。
无论如何,你可以有一个像这样的视图函数: 1)首先 _view / first_measurements
图: function(doc){ if(doc.type =='measurement_result'){ var first = doc.measurements [0]; emit([first.measurement_id,doc.serial_nr,first.timestamp],first.data) } }
减少: _stats
2) _view /最新 地图: function(doc){ if(doc.type =='measurement_result'){ var last = doc.measurements [doc.measurements.length-1]; emit([last.measurement_id,doc.serial_nr,last.timestamp],last.data) } }
减少: _stats
//我对measurement_id和文档的id之间的区别以及必须具有的唯一性感到有点困惑,所以我可能还不能回答这个问题,但听起来你可以使用startkey和endkey范围组合可能是descending = false ...来得到你想要的东西..而且include_doc = true可能会派上用场检索发出值的文档....(或数据库中的任何其他文档:-))..无论如何希望这有帮助