Группировать по 2 полям как 1 поле

Я пытаюсь сгруппировать пользователей по их основным и второстепенным ролям и подсчитать количество пользователей с указанными ролями. Список пользователей выглядит так:

[
    {
        _id: 1,
        roles: {
            primary: 'Cook',
            secondary: null
        }
    },
    {
        _id: 2,
        roles: {
            primary: 'Waiter',
            secondary: 'Cashier'
        }
    },
    {
        _id: 3,
        roles: {
            primary: 'Cashier',
            secondary: 'Bar Tender'
        }
    }
]

И результат должен быть примерно таким:

[
    {
        role: 'Cook',
        count: 1
    },
    {
        role: 'Waiter',
        count: 1
    },
    {
        role: 'Cashier',
        count: 2
    }
]

Я не совсем уверен, если это вообще возможно сделать, по крайней мере, в одном $group вызов.

1 ответ

Решение

Вы можете поместить оба значения поля в массив, $unwind а потом $group:

db.collection('crap').aggregate([
  { "$project": {
      "roles": {
        "$filter": {
          "input": ["$roles.primary","$roles.secondary"],
          "cond": { "$ne": [ "$$this", null ] }
        }
      }
  }},
  { "$unwind": "$roles" },
  { "$group": {
    "_id": "$roles",
    "count": { "$sum": 1 }  
  }}
])

Мы используем $filter удалить любой null значения в проецируемом массиве.

На документах в вопросе это даст вам:

{
    "_id" : "Bar Tender",
    "count" : 1.0
}

{
    "_id" : "Waiter",
    "count" : 1.0
}

{
    "_id" : "Cashier",
    "count" : 2.0
}

{
    "_id" : "Cook",
    "count" : 1.0
}
Другие вопросы по тегам