Агрегация mongodb: средние продажи в час

У меня есть коллекция с распродажами. Теперь мне нужно получить среднее количество продаж в час в пределах диапазона дат.

До сих пор у меня есть такой запрос:

db.getCollection('sales').aggregate({
    "$match": {
        $and: [
            { "createdAt": { $gte: ISODate("2018-05-01T00:00:00.000Z") } },
            { "createdAt": { $lt: ISODate("2018-10-30T23:59:00.000Z") } },
        ]
    }
},{ 
    "$project": {
      "h":{"$hour":"$createdAt"},
     }
},{ 
     "$group":{ 
        "_id": "$h",
        "salesPerHour": { $sum: 1 },
      },
},{
    "$sort": { "salesPerHour": -1 }
});

Результат выглядит так: {"_id": 15, "salesPerHour": 681.0}

Как я могу получить среднее значение salesPerHour вместо суммы?

Обновление 1 => Пример документа.

{
    "_id" : "pX6jj7j4274J9xpSA",
    "idFiscalSale" : "48",
    "documentYear" : "2018",
    "paymentType" : "cash",
    "cashReceived" : 54,
    "items" : [...],
    "customer" : null,
    "subTotal" : 23.89,
    "taxTotal" : 3.7139,
    "total" : 23.89,
    "rewardPointsValue" : 0,
    "rewardPointsEarned" : 24,
    "discountValue" : 0,
    "createdAt" : ISODate("2018-04-24T00:00:00.201Z")
}
3
0
1 050
2

Ответы 2

Вы можете использовать ниже агрегированный запрос.

db.sales.aggregate([
  {"$match":{
    "createdAt":{
      "$gte":ISODate("2018-05-01T00:00:00.000Z"), 
      "$lt":ISODate("2018-10-30T23:59:00.000Z")
    }
  }},
  {"$group":{
    "_id":{"$hour":"$createdAt"},
    "salesPerHour":{"$sum":1}
  }},
  {"$group":{
    "_id":null,
    "salesPerHour":{"$avg":"$salesPerHour"}
  }}
])

Энтони, это правильно. Это вернет среднее значение всех часов.

Luciano 31.10.2018 15:54

ответ сработал для вас? Пожалуйста, примите, если это сработало,

s7vr 03.11.2018 18:23

Спасибо @Veeram, но я не получил ожидаемого результата. {"_id" : null,"salesPerHour" : 339.153846153846}

Luciano 20.06.2019 14:21

Np каков ожидаемый вывод json? Какое поле имеет значение продажи?

s7vr 20.06.2019 14:24

Что-то вроде: [{"_id" : 8,"salesPerHour" : 11}, {"_id" : 9,"salesPerHour" : 5}, {"_id" : 10,"salesPerHour" : 15},...]. Где _id - это час дня. Обычно мне нужно получить среднее количество продаж за каждый час дня.

Luciano 20.06.2019 14:27

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

s7vr 20.06.2019 14:35

Что вы имеете в виду под «полем, в котором продают»? Вы можете увидеть и пример документа в «Обновление 1» вопроса.

Luciano 20.06.2019 14:41

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

s7vr 20.06.2019 14:57

Я рассчитываю это в группе $. Каждые продажи, сделанные с 8 до 9 утра, добавляются с _id: 8 и суммируются в salesPerHour. Это вычисляемое поле, я думал, что $ avg даст мне среднее число этого значения. Может что-то упускаю ... :(

Luciano 20.06.2019 15:05

Ну нет среднего для суммируемого поля, так как это только одно значение. Другое дело, если вы собираете все значения, которые являются одним, и вы усредняете эти значения за час, среднее значение всегда равно 1. $ sum: 1 просто подсчитывает случаи продажи.

s7vr 20.06.2019 15:07

Вы всегда можете получить средние продажи за день, усреднив все почасовые интервалы значений. Вы бы этого хотели?

s7vr 20.06.2019 15:10

Хорошо, теперь я понял. Еще раз спасибо за объяснение! К сожалению, количество продаж в день не подходит для работы, мне нужно его ежечасно, чтобы оценить часы работы магазина. Я подумываю создать временную коллекцию с num_of_sales_per_hour каждого дня, а затем вычислить среднее значение.

Luciano 20.06.2019 15:33

Вы можете попробовать ниже агрегирование

Вы должны использовать оператор агрегации $avg с полем salesPerHour

db.collection.aggregate([
  { "$match": {
    "$and": [
      { "createdAt": { "$gte": ISODate("2018-05-01T00:00:00.000Z") }},
      { "createdAt": { "$lt": ISODate("2018-10-30T23:59:00.000Z") }}
    ]
  }},
  { "$group": {
    "_id": { "$hour": "$createdAt" },
    "salesPerHour": {
      "$avg": "$salesPerHour"
    }
  }}
])

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

Ashh 31.10.2018 15:56
salesPerHour это не поле для сбора. Используя ваш пример, я получаю salesPerHour=null
Luciano 31.10.2018 16:01

Другие вопросы по теме