MongoDB - преобразовать строку в метку времени, сгруппировать по часам - PullRequest
0 голосов
/ 13 марта 2020

В коллекции хранятся следующие документы:

{
  "REQUESTTIMESTAMP" : "26-JUN-19 01.34.10.095000000 AM",
  "UNHANDLED_INTENT" : 0,
  "USERID" : "John",
  "START_OF_INTENT_SKILL_CONVERSATION" : 0,
  "PROPERTYCODE" : ""
}  

Я хочу сгруппировать их по часам (которые мы получим из 'REQUESTTIMESTAMP')

Ранее этот документ хранился в коллекции другим способом, где у меня было отдельное поле для часов, и я использовал это поле часов для группировки:

Предыдущий запрос агрегации:

collection.aggregate([
    {'$match': query}, {
        '$group': {
            "_id": {
                "hour": "$hour",
                "sessionId": "$sessionId"
            }
        }
    }, {
        "$group": {
            "_id": "$_id.hour",
            "count": {
                "$sum": 1
            }
        }
    }
])    

Предыдущая структура коллекции:

{
  "timestamp" : "1581533210921",
  "date" : "12-02-2020",
  "hour" : "13",
  "month" : "02",
  "time" : "13:46:50",
  "weekDay" : "Wednesday",
  "__v" : 0
}

Как мне выполнить то же самое Предыдущий запрос агрегации с новой структурой документа ( После извлечения часов из поля ' REQUESTTIMESTAMP '?)

Ответы [ 3 ]

0 голосов
/ 13 марта 2020

Проблема в том, что названия месяцев не поддерживаются MongoDB. Либо вы пишете много кода, либо используете библиотеки, например моменты. js. Сначала обновите ваш REQUESTTIMESTAMP до нужного объекта Date, затем вы можете сгруппировать его.

db.collection.find().forEach(function (doc) {
   var d = moment(doc.REQUESTTIMESTAMP, "DD-MMM-YY hh.mm.ss.SSS a");
   db.collection.updateOne(
      { _id: doc._id },
      { $set: { date: d.toDate() } }
   );
})

db.collection.aggregate([
   {
      $group: {
         _id: { $hour: "$date" },
         count: { $sum: 1 }
      }
   }
]) 
0 голосов
/ 13 марта 2020

Если вы не можете обновить БД с помощью поля фактической даты и все еще хотите продолжить работу с существующим форматом, попробуйте этот запрос, чтобы добавить поле часа, извлеченное из данного строкового поля REQUESTTIMESTAMP :

Запрос:

db.collection.aggregate([
    {
        $addFields: {
            hour: {
                $let: {
                    /** split string into three parts date + hours + AM/PM */
                    vars: { hour: { $slice: [{ $split: ["$REQUESTTIMESTAMP", " "] }, 1, 2] } },
                    in: {
                        $cond: [{ $in: ["AM", "$$hour"] }, // Check AM exists in array
                        { $toInt: { $substr: [{ $arrayElemAt: ["$$hour", 0] }, 0, 2] } }, // If yes then return int of first 2 letters of first element in hour array
                        { $add: [{ $toInt: { $substr: [{ $arrayElemAt: ["$$hour", 0] }, 0, 2] } }, 12] } ] // If PM add 12 to int of first 2 letters of first element in hour array
                    }
                }
            }
        }
    }
])

Тест: MongoDB-Playground

0 голосов
/ 13 марта 2020

Вы должны преобразовать свою метку времени в Date объект, затем взять час от вашего объекта даты.

db.collection.aggregate([{
    '$match': query
}, {
    $project: {
        date: {
            $dateFromString: {
                dateString: '$REQUESTTIMESTAMP',
                format: "%m-%d-%Y" //This should be your date format
            }
        }
    }
}, {
    $group: {
        _id: {
            hour: {
                $hour: "$date"
            }
        }
    }
}])
...