RethinkDB - 如何在分组数据上返回滑动窗口

时间:2016-01-16 14:30:25

标签: rethinkdb

我有一些对象:

[
  { 'time': 1, 'data': { '1': 10, '2': 100} },
  { 'time': 2, 'data': { '1': 20, '2': 100} },
  { 'time': 3, 'data': { '1': 30, '2': 200} },
  { 'time': 4, 'data': { '1': 40, '2': 100} },
  { 'time': 5, 'data': { '1': 50, '2': 300} },
  { 'time': 6, 'data': { '1': 60, '2': 200} }
]

和两个变量widthoverlap

  • width - 最长'values'列表
  • overlap - 互助值的数量

假设width = 3overlap = 2。有没有办法获得以下?

[ { 'key': '1',
    'rows': [ { 'time': 1, 'values': [10,20,30] },
              { 'time': 2, 'values': [20,30,40] },
              { 'time': 3, 'values': [30,40,50] },
              { 'time': 4, 'values': [40,50,60] }
            ]
  },
  { 'key': '2',
    'rows': [ { 'time': 1, 'values': [100,100,200] },
              { 'time': 2, 'values': [100,200,100] },
              { 'time': 3, 'values': [200,100,300] },
              { 'time': 4, 'values': [100,300,200] }
            ]
  } ]

到目前为止,我设法得到了这个:

[ { 'key': '1',
    'row': { 'time': 1, 'values': [10,20,30,40,50,60] }
  },
  { 'key': '2',
    'row': { 'time': 1, 'values': [100,100,200,100,300,200] }
  } ]

使用:

.concatMap(function(item) {
  return item('data').keys().map(function(key) {
    return {
      'key': key,
      'row': { 
        'time': item('time'),
        'values': [item('data')(key)]
      }
    }
  })
})
.group('key')
.ungroup()
.map(function(list) { 
  return list('reduction').reduce(function(left, right) {
    return {
      'key': left('key'),
      'row': {
        'time': left('row')('time'),
        'values': left('row')('values').union(right('row')('values'))
      }
    }
  })
})

也许我需要添加一些东西或改变一切?

感谢。

2 个答案:

答案 0 :(得分:1)

这与mlucy的解决方案非常相似,但它并不假设time字段是连续的整数。数据在time之前按concatMap排序 - 对于大型数据集,这应该使用索引来完成。

r.expr(data)
 .orderBy('time')
 .concatMap(function (row) {
   return row('data').coerceTo('array').map(function (pair) {
     return { key: pair(0), value: pair(1), time: row('time') };
   });
 })
 .group('key')
 .ungroup()
 .map(function (g) {
   let rows = g('reduction').count().do(function (c) {
     return r.range(c.sub(2)).map(function (i) {
       let values = r.range(3).map(function (j) {
         return g('reduction')(i.add(j))('value');
       }).coerceTo('array');
       return { 'time': g('reduction')(i)('time'), 'values': values };
     }).coerceTo('array');
   });
   return { key: g('group'), rows: rows };
 })

答案 1 :(得分:0)

你可能想要这样的东西:

r.table('test').orderBy('time').concatMap(function(row) {
  return row('data').coerceTo('array');
}).group(function(pair) {
  return pair(0);
}).map(function(pair) {
  return pair(1);
}).ungroup().map(function(group) {
  return {
    key: group('group'),
    rows: group('reduction').do(function(x) {
      return r.range(x.count().sub(2)).map(function(i) {
        return {
          time: i,
          values: r.range(3).map(function(o) {
            return x(i.add(o));
          }).coerceTo('array')
        };
      }).coerceTo('array');
    })
  };
})

.sub(2).range(3)需要根据宽度和重叠进行更改。)