Соберите 3 больших списка по нескольким поддокументам в MongoDB - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть несколько сотен документов, которые я извлекаю из коллекции в MongoDB.

В этом упрощенном примере я спроецировал каждый документ на 3 списка - примерно так:

{
   lats: [],
   lngs: [],
   velocity_smooth: []
}

Каждый из списков, вероятно, будет довольно длинным, в среднем около 2000 элементов каждый.

Три списка на самом деле являются справочной таблицей (lat, long) -> speed , поэтому порядок важен.

Я хотел бы объединить их, чтобы найти среднюю скорость для всех документов на каждом широте / долготе (которую я усекаю до 4 дп). Моей целью было бы объединить вышеуказанный набор документов в новый набор, по одному для каждого сопоставления (lat, long) -> average_speed. Я все еще ожидаю большое количество документов в конце.

Что-то вроде:

[
  {
    lat: 12.34,
    long: 56.78,
    average_spd: 4.5
  },
  {
    lat: 23.45,
    long: 67.89,
    average_spd: 3.2
  },
  ...
]

Я пробовал несколько агрегатов, чтобы заставить это работать, но продолжаю удар по ограничениям памяти или тайм-аутам, что подсказывает мне, что я делаю это неправильно.

Я могу получить один документ, содержащий 3 списка списков, объединяя массивы следующим образом:

$group: {
  _id: null,
  all_lats: {
    $push: '$lats'
  },
  all_lngs: {
    $push: '$lngs'
  },
  all_spds: {
    $push: '$speeds'
  }
}

Я могу уменьшить один из них, используя $arrayConcat, чтобы уменьшить списки, но если я попытаюсь сделать это с более чем одним из них, я go превышает максимальный размер BSON:

{
  data: {
    $reduce: {
      input: '$all_lats',
      initialValue: [],
      'in': {
        $concatArrays: [
          '$$value',
          '$$this'
        ]
      }
    }
  }
}

Я также попытался использовать $unwind для извлечения каждого отдельного элемента списка, но это заняло время в 3-м списке:

{
    '$unwind': '$lats'
}, {
    '$unwind': '$lngs'
}, {
    '$unwind': '$spd'
}

Это, похоже, дает мне документы, которые я хотел бы сгруппировать, затем я попытался добавить Следующее, чтобы получить среднюю скорость:

{
    '$group': {
        '_id': {
            'lat': '$lats', 
            'lng': '$lngs'
        }, 
        'average_speed': {
            '$avg': '$spd'
        }
    }
}

Такое ощущение, что это должно работать, но на самом деле все, что происходит, это то, что процессор работает на 100% и никогда не возвращает результат.

Я могу выполнить ту же группировку в python для необработанных данных в ~ 1, поэтому создается впечатление, что должен быть способ сделать это с агрегациями без значительного времени ожидания.

Кто-нибудь может порекомендовать лучший конвейер?

Мне было интересно, может ли мне помочь создание геопространственного индекса, но вопрос о порядке агрегирования все еще остается.

...