使用CouchDB自定义ID的最新或第一个结果

时间:2013-10-14 08:50:20

标签: database-design statistics couchdb

我一直试图解决这个问题一段时间,阅读大量的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。一个单元可以多次进行测试。

我正在尝试构建的视图如下:

  1. 首次检测设备时检索所有数据。
  2. 检索单位测试的最新时间的所有数据。
  3. 检索一个measurement_id的所有度量,但仅针对最早的结果。如果任何一个单元已经过多次测试,则只应包括第一次测试的测量结果。
  4. 检索一个measurement_id的所有度量,但仅针对最新结果(与最早结果相同的规则)。
  5. 目标是缩小data字段以计算averageminmaxstandard 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并且只返回最新/最旧的,但我无法弄清楚如何。

    希望这可以解决一下这个问题。

1 个答案:

答案 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可能会派上用场检索发出值的文档....(或数据库中的任何其他文档:-))..无论如何希望这有帮助