агрегация mongodb с $ last, $ first при обновлении значений с нуля, если запись не найдена - PullRequest
0 голосов
/ 20 марта 2020

Пожалуйста, проверьте этот запрос

db.orders.aggregate([
    {
        '$match': {
            "userId" : ObjectId("5e7147ada3141a63a0dbc154"),
        "adminId" :  ObjectId("5e7147e8fc64ed3d2473o2fec"),
            '$or': [{
                    'orderedOnDate': ISODate("2020-03-21T00:00:00Z")
                    }, 
                     {
                      'orderedOnDate': ISODate("2020-03-14T00:00:00Z")
                    }]
              }
         }, 
        {
        '$unwind': {
            'path': '$totalOrders',
          },
        },
       {
        '$group': {
            '_id': {
                'code': '$totalOrders.code',
                'date': '$orderedOnDate',
            },
            'orderCount': {
                '$last': '$totalOrders.orderCount',
            },
             'sortedDate': {
                '$last': '$orderedOnDate'
            }
        }
    }
    , {
        '$sort': {
            'sortedDate': 1
        }
    }, {
        '$group': {
            '_id': '$_id.code',
            'orderCount': {
                '$last': '$orderCount'
            },
            'previousOrderCount': {
                '$first': '$previousOrderCount'
            },
           'sortedDate': {
                '$last': '$sortedDate'
            },
            'previousSortedDate': {
                '$first': '$sortedDate'
            },

        }
    },
      {
        '$project': {
            "_id": 0,
           'code':1
            'sortedDate': 1,
            'orderCount': 1,
            'previousWeekCount': [
                {
                    'sortedDate': '$previousOrderCount',
                    'orderCount': '$previousOrderCount',

                }
            ]
        }
    }])

В приведенном выше запросе я пытаюсь получить данные за завтрашнюю дату и дату D-7, запрос работает, как и ожидалось, если он находит запись для обеих дат, теперь проблема возникает, когда нет записи для D-7-го дня, тогда $ first и $ last имеют одинаковую дату, следовательно, они также показывают те же данные в previousWeekCount. Но я хочу вставить значение 0, если в течение дня D-7 нет записи. Также мне нужно сохранить структуру $ project, так как она была отправлена ​​на внешний интерфейс. Я пробовал несколько вещей, таких как $ ifnull, также пробовал $ cond на дата, но ничего не сработало, какие-либо предложения или как это можно решить. Ниже приведен пример документа, в котором нет записи даты D-7

{
    "_id" : ObjectId("5e73089d44eb7a50708167fc"),
    "orderedOnDate" : ISODate("2020-03-21T00:00:00.000Z"),
     "totalOrders" : [
            {      
                "orderCount" : 10,
                "code" : "#001",
            },
            {      
                "orderCount" : 46,
                "code" : "#002",
            },
    ],
}

Теперь, если нет записи дня D-7, могу ли я show orderCount: 0 против кодов, я не хочу сохранять документ D-7, просто нужно показать 0 значений

1 Ответ

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

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

db.collection.aggregate([
   {
      $match: {
         userId: ObjectId("5e7147ada3141a63a0dbc154"),
         orderedOnDate: { $in: [moment.utc().startOf('day').toDate(), moment.utc().startOf('day').subtract(7, 'days').toDate()] }
      }
   },
   { $sort: { orderedOnDate: 1 } },
   {
      $group: {
         _id: null,
         lastWeekOrders: { $first: "$$ROOT" },
         todayOrders: { $last: "$$ROOT" }
      }
   },
   {
      $set: {
         lastWeekOrders: {
            $cond: {
               if: { $eq: ["$lastWeekOrders.orderedOnDate", moment.utc().startOf('day').subtract(7, 'days').toDate()] },
               then: "$lastWeekOrders",
               else: {
                  orderedOnDate: moment.utc().startOf('day').subtract(7, 'days').toDate(),
                  totalOrders: [{ orderCount: 0 }]
               }
            }
         }
      }
   },
   {
      $set: {
         todayOrders: {
            $cond: {
               if: { $eq: ["$todayOrders.orderedOnDate", moment.utc().startOf('day').toDate()] },
               then: "$todayOrders",
               else: {
                  orderedOnDate: moment.utc().startOf('day').toDate(),
                  totalOrders: [{ orderCount: 0 }]
               }
            }
         }
      }
   },
])
...