Совпадение, когда элемент массива появляется перед другим элементом (MongoDB)

#mongodb #mongodb-query #aggregation-framework

#mongodb #mongodb-запрос #агрегация-фреймворк

Вопрос:

Документы в моей коллекции имеют следующую структуру для заказа:

 [
{
  OrderId: 'ID1',
  StatusLog: [
    {
      Timestamp: 'Some ISO Date',
      Status: 1,
      Reason: 'Because',
      User: 'User1'
    },
    {
      Timestamp: 'Some ISO Date',
      Status: 2,
      Reason: 'No Idea',
      User: 'User2'
    },
    {
      Timestamp: 'Some ISO Date',
      Status: 3,
      Reason: 'Because',
      User: 'User2'
    },
    {
      Timestamp: 'Some ISO Date',
      Status: 2 // NOTE: status can go back to 2,
      Reason: 'Some Idea',
      User: 'User1'
    }
},
{
  OrderId: 'ID2',
  StatusLog: [
    {
      Timestamp: 'Some ISO Date',
      Status: 1,
      Reason: 'Because',
      User: 'User1'
    },
    {
      Timestamp: 'Some ISO Date',
      Status: 2, 
      Reason: 'The reason to include in results',
      User: 'User2'
    },
    {
      Timestamp: 'Some ISO Date',
      Status: 3, 
      Reason: 'Because',
      User: 'User2'
    }
}
]
  

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

     [
        {
            $unwind: {
                path: '$StatusLog'
            }
        },

        {
            $match: {
                'StatusLog.Status': 2
            }
        },

        {
            $group: {
                _id: {
                    'reason': '$StatusLog.Reason',
                    'user': '$StatusLog.User'
                },
                'orderCount': { $sum: 1 }
            }
        },
    ]
  

Результат приведенного выше запроса находится в точном формате, который мне нужен. Тем не менее, я хочу добавить эти фильтры в запрос:

  1. заказ должен включать элемент StatusLog со статусом = 2
  2. заказ должен включать предыдущий элемент StatusLog со статусом = 3
  3. каждый порядок должен учитываться только один раз

Итак, из приведенного выше массива примеров данных только порядок с OrderID=’ID1′, и результат должен быть:

 [
{ 
    "_id" : {
        "reason" : "The reason to include in results", 
        "user" : "User2"
    }, 
    "orderCount" : 1.0
}
]
  

Любая помощь будет оценена.

Комментарии:

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

Ответ №1:

  • $unwind деконструировать StatusLog массив
  • $match Состояние в 2 или 3
  • $group пользователем и make array of Status , получаем первую причину и получаем orderCount Status 2
  • $match фильтруйте пользователей, имеющих статус во 2 и 3, используя $all
 db.collection.aggregate([
  { $unwind: "$StatusLog" },
  { $match: { "StatusLog.Status": { $in: [2, 3] } } },
  {
    $group: {
      _id: "$StatusLog.User",
      Status: { $push: "$StatusLog.Status" },
      Reason: { $first: "$StatusLog.Reason" },
      orderCount: {
        $sum: { $cond: [{ $eq: ["$StatusLog.Status", 2] }, 1, 0] }
      }
    }
  },
  { $match: { Status: { $all: [2, 3] } } }
])
  

Игровая площадка