Преобразуйте массив в новое поле, используя ключи как значения этого массива и значения как частоту этих элементов (структура агрегирования) - PullRequest
1 голос
/ 05 мая 2020

У меня есть эта проблема, но я не могу ее решить.
Мне нужно преобразовать массив s в новое поле с именем shares.
В этом новом поле есть новые ключи и новые значения .
Предположим, у меня есть следующие документы:

{
  'name': 'igor',
  's': ['a', 'a', 'a', 'b', 'b']
},
{
  'name': 'jones',
  's': ['c', 'b']
}

Ожидаемый результат:

{
  'name': 'igor',
  'shares': {
     'a': 3
     'b': 2
  }
},
{
  'name': 'jones',
  'shares': {
     'c': 1
     'b': 1
  }
}

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

Вы можете попробовать следующий запрос агрегирования:

db.collection.aggregate([
    /** unwind `s` array */
    {
      $unwind: "$s"
    },
    /** group on unique pairs of `_id + s` & retain name field, count sum of matching docs */
    {
      $group: { _id: { k: "$s", _id: "$_id" }, name: { $first: "$name" }, v: { $sum: 1 } }
    },
    /** group on unique pairs of just `_id` & retain name field, push docs into shares array `[{k :..., v:...}]` */
    {
      $group: { _id: "$_id._id", name: { $first: "$name" }, shares: { $push: { k: "$_id.k", v: "$v" } } }
    },
    /** Re-create shares field from array to object */
    {
      $addFields: { shares: { $arrayToObject: "$shares" } }
    }
  ])

Тест: mongoplayground

0 голосов
/ 05 мая 2020

Это плохая практика добавлять разнородные элементы (в вашем случае: 'a': 3, 'b': 2) в массив, я преобразовал тип shares во что-то вроде:

{
    key: "$_id.shares",
    count: "$count"
}

Вам нужно сделать в следующем порядке:

  1. Размотка массива s.
  2. Группировка по составным _id name и s.
  3. Снова группировка по _id _id.name и pu sh объекты типа key и count в массив shares.

Вы можете попробовать следующий запрос:

db.collection.aggregate([
  {
    $unwind: "$s"
  },
  {
    $group: {
      _id: {
        name: "$name",
        shares: "$s"
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $group: {
      _id: "$_id.name",
      shares: {
        $push: {
          key: "$_id.shares",
          count: "$count"
        }
      }
    }
  }
])

Выход

[
  {
    "_id": "jones",
    "shares": [
      {
        "count": 1,
        "key": "c"
      },
      {
        "count": 1,
        "key": "b"
      }
    ]
  },
  {
    "_id": "igor",
    "shares": [
      {
        "count": 3,
        "key": "a"
      },
      {
        "count": 2,
        "key": "b"
      }
    ]
  }
]

MongoPlayGroundLink

...