RethinkDB - Как объединять и усреднять объекты

У меня есть документы, структурированные следующим образом:

[
  {
    'post': 1,
    'tags': [1, 2],
    'poll': {
      'a': 2,
      'b': 2
    }
  },
  {
    'post': 1,
    'tags': [3],
    'poll': {
      'a': 4,
      'b': 6
    }
  },
]

Как я могу объединить их так, чтобы tags будет объединение всех тегов в этих сообщениях и poll будет усреднено? Из приведенного выше примера результат должен выглядеть следующим образом:

[
  {
    'post': 1,
    'tags': [1, 2, 3],
    'poll': {
      'a': 3,
      'b': 4
    }
  }
]

Благодарю.

2 ответа

Решение

Я думаю, что мы можем использовать map-reduce так как мы превращаем много документов в один. Нечто подобное должно работать:

r.expr([
  {
    'post': 1,
    'tags': [1, 2],
    'poll': {
      'a': 2,
      'b': 2
    }
  },
  {
    'post': 1,
    'tags': [3],
    'poll': {
      'a': 4,
      'b': 6,
    }
  },
])
  .merge(function(doc) {
    return {
      'poll': doc('poll').coerceTo('array').map(function(poll) { return [poll(0), [poll(1)]] }).coerceTo('object')
    }
  })  

  .reduce(function(left, right) {
    return {
      'post': left('post'),
      'tags': left('tags').setUnion(right('tags')),
      'poll': left('poll').keys().setUnion(right('poll').keys()).map(function(k) {
        return [k, 
          left('poll')(k).default([]).union(right('poll')(k).default([]))
          ]
      })
    }
  })

  .merge(function(doc) {
    return {
      poll: doc('poll').map(function(poll) {
        return [poll(0), poll(1).avg()]
      }).coerceTo('object')
    }
  })

Это производит:

{
    "poll": {
        "a": 3,
        "b": 4
    },
    "post": 1,
    "tags": [1, 2, 3]
}

Исправлена ​​версия, изначально предложенная kureikain:

r.expr([
  {
    'post': 1,
    'tags': [1, 2],
    'poll': {
      'a': 2,
      'b': 2
    }
  },
  {
    'post': 1,
    'tags': [3],
    'poll': {
      'a': 4,
      'b': 6,
    }
  },
  {
    'post': 1,
    'tags': [2],
    'poll': {
      'a': 1,
      'b': 3,
    }
  },
])
.merge(function(doc) {
  return {
    'poll': doc('poll').coerceTo('array').map(function(poll) { return [poll(0), [poll(1)]] }).coerceTo('object')
  }
})  
.reduce(function(left, right) {
  return {
    'post': left('post'),
    'tags': left('tags').setUnion(right('tags')),
    'poll': left('poll').keys().map(function(k) {
      return [k, left('poll')(k).default([]).union(right('poll')(k).default([]))]
    }).coerceTo('object')
  }
})
.merge(function(doc) {
  return {
    poll: doc('poll').keys().map(function(k) {
      return [k, doc('poll')(k).avg()]
    }).coerceTo('object')
  }
})
Другие вопросы по тегам