Mapreduce 如何编写CouchDB视图以获得当前活动的服务器,并给出每个服务器的开始时间戳和结束时间戳?

Mapreduce 如何编写CouchDB视图以获得当前活动的服务器,并给出每个服务器的开始时间戳和结束时间戳?,mapreduce,couchdb,Mapreduce,Couchdb,我有一组文档,其中包含服务器名,以及该服务器的开始时间戳和结束时间戳。例如 [ { serverName: "Houston", startTimestamp: "2018/03/07 17:52:13 +000", endTimestamp: "2018/03/07 18:50:10 +000" }, { serverName: "Canberra", startTimestamp: "20

我有一组文档,其中包含服务器名,以及该服务器的开始时间戳和结束时间戳。例如

[
    {
        serverName: "Houston",
        startTimestamp: "2018/03/07 17:52:13 +000",
        endTimestamp: "2018/03/07 18:50:10 +000"
    },
    {
        serverName: "Canberra",
        startTimestamp: "2018/03/07 18:48:09 +000",
        endTimestamp: "2018/03/07 20:10:00 +000"
    },
    {
        serverName: "Melbourne",
        startTimestamp: "2018/03/08 01:43:13 +000",
        endTimestamp: "2018/03/08 12:09:10 +000"
    }        
]
有了这些数据,给定一个时间戳,我需要获得该时间点的活动服务器列表

比如说。对于上述数据中的
TS=“2018/03/07 18:50:00+000”
活动服务器列表为
[“休斯顿”、“堪培拉”]

是否可以仅使用CouchDB视图来实现这一点。如果是这样的话,怎么办


注意:最初我尝试了以下方法。在map函数中,我发出两个文档

  • 1带有
    key=doc.startTimestsamp
    value={“station\u add”:doc.station}
  • 1带有
    key=doc.startEndtsamp
    value={“station\u rem”:doc.station}

我的目的是在reduce函数中迭代这些操作,添加
“station\u add”
中的站点,并删除
“stations\u rem”
中的站点。但是我发现,CouchDB没有提到任何关于reduce函数中值的排序问题

例如,如果您可以接受固定的周期,并且不介意查看结果可能需要的额外磁盘空间,那么您可以创建每小时活动服务器的视图

迭代开始和结束之间的时间段,并发出在此期间每个服务器联机的时间:

function(doc) {
  var start = new Date(doc.startTimestamp).getTime()
  var end = new Date(doc.endTimestamp).getTime()
  var msPerPeriod = 60*60*1000
  var msOfflineInFirstPeriod = start % msPerPeriod
  var firstPeriod = start - msOfflineInFirstPeriod

  var msOnlineInLastPeriod = end % msPerPeriod
  var lastPeriod = end - msOnlineInLastPeriod

  if (firstPeriod === lastPeriod) {
    // The server was only online within one period.
    emit([new Date(firstPeriod), doc.serverName], [1, msOnlineInLastPeriod - msOfflineInFirstPeriod])
  } else {
    // The server was online over multiple periods.
    emit([new Date(firstPeriod), doc.serverName], [1,msPerPeriod - msOfflineInFirstPeriod])
    for (var period = firstPeriod + msPerPeriod; period < lastPeriod; period += msPerPeriod) {
      emit([new Date(period), doc.serverName], [1, msPerPeriod])
    }
    emit([new Date(lastPeriod), doc.serverName], [1,msOnlineInLastPeriod])
  }
}
功能(doc){
var start=新日期(doc.startTimestamp.getTime())
var end=新日期(doc.endTimestamp).getTime()
var MsperPerPerPerPeriod=60*60*1000
var msOfflineInFirstPeriod=开始%msPerPerPerPerPeriod
var firstPeriod=start-msOfflineInFirstPeriod
var msOnlineInLastPeriod=结束%MsperPerPerPerPeriod
var lastPeriod=结束-msOnlineInLastPeriod
如果(第一个周期===最后一个周期){
//服务器仅在一段时间内联机。
发出([new Date(firstPeriod),doc.serverName],[1,msOnlineInLastPeriod-msOfflineInFirstPeriod])
}否则{
//服务器在多个时间段内处于联机状态。
发出([new Date(firstPeriod),doc.serverName],[1,msperperperiod-msOfflineInFirstPeriod])
对于(var period=firstPeriod+msperiod;period
如果您希望总数不包含服务器名称,只需添加一个带有内置快捷方式的reduce函数
\u sum
。您将获得在此期间联机的服务器数作为第一个数字,服务器在此期间联机的毫秒数作为第二个数字

如果将年、月和日作为第一个关键点发射,则可以播放视图。然后,您可以在查询时使用group_级别来获得更精细或更粗略的概览

请记住,此视图在磁盘上可能会变大,因为必须存储每一行,并且存储每个组级别的中间结果。因此,您不应该将时段持续时间设置得太小,例如,每秒发送一行将占用大量磁盘空间