Необходимо объединить 3 сборника для mongodb, чтобы найти агрегированные данные - PullRequest
1 голос
/ 07 ноября 2019

Мои знания в mongodb мало. У меня есть список магазинов как коллекция магазинов, в которой хранятся только основные сведения

Store collection:
[
  {
    "id": "5dc25092d972e71c3b3e6e87",
    "name": "Chad store",
  },
  {
    "id": "5dc2899bfd1ea02f0fceb9ab",
    "name": "Bad store",
  }
]

У меня есть коллекция записей сигналов, в которой есть несколько записей сигналов для каждого магазина.
записей сигналов, как нет. сигнальных полос, уровня сигнала и т. д. У немногих магазинов может не быть записей о сигналах.

Signal records:

[
  {
    "id": "5dc250e0d972e71c3b3e6e88",
    "signalStrength": -180,
    "signalbars": "3",
    "employee": "5db59227f0204855654075ee",
    "store": "5dc25092d972e71c3b3e6e87"
  },
  {
    "id": "5dc251f723760a24de167f8e",
    "signalStrength": -180,
    "signalbars": "3",
    "employee": "5db59227f0204855654075ee",
    "store": "5dc25092d972e71c3b3e6e87"
  },
  {
    "id": "5dc289affd1ea02f0fceb9ac",
    "signalStrength": -80,
    "signalbars": "3",
    "employee": "5db59227f0204855654075ee",
    "store": "5dc2899bfd1ea02f0fceb9ab"
  }
]

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

Speed Tests:

[
  {
    "id": "5dc2c170e26c4a484051f4af",
    "ping": 10,
    "downloadSpeed": 7.66,
    "uploadSpeed": 4.22,
    "employee": "5dc2b9467a56f3446dcaf8f6",
    "store": "5dc25092d972e71c3b3e6e87"
  },
  {
    "id": "5dc3a0a92588214e1a938a34",
    "ping": 10,
    "downloadSpeed": 7.66,
    "uploadSpeed": 4.22,
    "employee": "5dc2b9467a56f3446dcaf8f6",
    "store": "5dc25092d972e71c3b3e6e87"
  }
]

Теперь мне нужно найти список магазинов вместе с количеством записей сигналов (если записей нет, тогда должно быть 0) и средним значением этих сигналов, средним числом полос сигналов, средней скоростью загрузки / выгрузки и т. Д. .

Expected output:

[
  {
    "store": "5dc25092d972e71c3b3e6e87",
    "storeName": "Chad store",
    "averageSignalStrength": -180,
    "averageUploadSpeed": 7.66
    "averageDownloadSpeed": 4.22
    "totalSpeedTests": 2
    "totalSpeedtestTesters": 1
  },
  {
    "store": "5dc2899bfd1ea02f0fceb9ab",
    "storeName": "Bad store",
    "averageSignalStrength": -80,
    "averageUploadSpeed": 0
    "averageDownloadSpeed": 0
    "totalSpeedTests": 0
    "totalSpeedtestTesters": 0
  }
]

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

Любая помощь будет великолепна

Ответы [ 2 ]

1 голос
/ 07 ноября 2019

Я использовал следующие агрегаты.

$ lookup для объединения сигналов и speedTests.

$ project для создания вычисляемых полей.

$ ifNull для обработки нулевых средних значений как 0.

$ setDifference для подсчета различных значений.

Вот требуемая агрегация:

db.store.aggregate([
  {
    $lookup: {
      from: "signals",
      localField: "id",
      foreignField: "store",
      as: "storeSignals"
    }
  },
  {
    $lookup: {
      from: "speedTests",
      localField: "id",
      foreignField: "store",
      as: "speedTests"
    }
  },
  {
    $project: {
      _id: 0,
      store: "$id",
      storeName: "$name",
      averageSignalStrength: {
        $ifNull: [
          {
            $avg: "$storeSignals.signalStrength"
          },
          0
        ]
      },
      averageUploadSpeed: {
        $ifNull: [
          {
            $avg: "$speedTests.uploadSpeed"
          },
          0
        ]
      },
      averageDownloadSpeed: {
        $ifNull: [
          {
            $avg: "$speedTests.downloadSpeed"
          },
          0
        ]
      },
      totalSpeedTests: {
        $size: "$speedTests"
      },
      totalSpeedtestTesters: {
        "$size": {
          "$setDifference": [
            "$speedTests.employee",
            []
          ]
        }
      }
    }
  },

])

Вывод:

[
  {
    "averageDownloadSpeed": 7.66,
    "averageSignalStrength": -180,
    "averageUploadSpeed": 4.22,
    "store": "5dc25092d972e71c3b3e6e87",
    "storeName": "Chad store",
    "totalSpeedTests": 2,
    "totalSpeedtestTesters": 1
  },
  {
    "averageDownloadSpeed": 0,
    "averageSignalStrength": -80,
    "averageUploadSpeed": 0,
    "store": "5dc2899bfd1ea02f0fceb9ab",
    "storeName": "Bad store",
    "totalSpeedTests": 0,
    "totalSpeedtestTesters": 0
  }
]

Детская площадка:

https://mongoplayground.net/p/MwJ26hAx996

1 голос
/ 07 ноября 2019

Вы можете использовать $lookup. Получить значение totalSpeedtestTesters в MongoDB немного сложно. Я думаю, вам нужно уникальное значение. Я рекомендую сделать это на стороне клиента

db.getCollection('Store').aggregate([
    {$lookup:
           {
             from: "Signal",
             localField: "id",
             foreignField: "store" ,
             as: "signals"
           }
    }
    ,{$lookup:
           {
             from: "Speed",
             localField: "id",
             foreignField: "store" ,
             as: "speeds"
           }
    }
    ,{$project :{ 
        store: "$id", 
        storeName: "$name",
        averageSignalStrength:  {
          $avg: "$signals.signalStrength"
        }
        ,averageUploadSpeed: {
          $avg: "$speeds.uploadSpeed"
        }
        ,averageDownloadSpeed:{
          $avg: "$speeds.downloadSpeed"
        }
        ,totalSpeedTests : {
          $size: "$speeds"
        }
        ,totalSpeedtestTesters:"$speeds.employee"
        }
     }
])
...