Использование $map в совокупности $group

#mongodb #aggregation-framework

Вопрос:

Мне нужно проанализировать некоторые коллекции баз данных mongo. Что мне нужно, чтобы извлечь имена и значения коллекции.

Вот как далеко я продвинулся:

 db.collection(coll.name)
  .aggregate([
    { $project: { arrayofkeyvalue: { $objectToArray: '$ROOT' } } },
    { $unwind: '$arrayofkeyvalue' },
    {
      $group: {
        _id: null,
        allkeys: { $addToSet: '$arrayofkeyvalue.k' },
      },
    },
  ])
  .toArray();
 

Это работает довольно хорошо. Я получаю все ключи. Однако я бы тоже хотел получить значения.

Итак, я подумал «кусок пирога» и заменил allkeys раздел allkeysandvalues разделом, который должен создавать карту с парами ключей и значений.

Подобный этому:

 db.collection(coll.name)
  .aggregate([
    { $project: { arrayofkeyvalue: { $objectToArray: '$ROOT' } } },
    { $unwind: '$arrayofkeyvalue' },
    {
      $group: {
        _id: null,
        allkeysandvalues: {
          $map: {
            input: '$arrayofkeyvalue',
            as: 'kv',
            in: {
              k: '$kv.k',
              v: '$kv.v',
            },
          },
        },
      },
    },
  ])
  .toArray();
 

Но это не работает. Я получаю сообщение об ошибке

 MongoError: unknown group operator '$map'
 

Кто-нибудь знает, как это решить?

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

1. Можете ли вы добавить mongoplayground.net ссылка с образцами данных, вы не можете использовать $map внутри $группы.

Ответ №1:

Этап конвейера $group требует выражения аккумулятора, поэтому вам нужно использовать $push вместо $map :

 {
    $group: {
        _id: null,
        allkeysandvalues: {
            $push: "$arrayofkeyvalue"
        }
    }
}
 

или

 {
    $group: {
        _id: null,
        allkeysandvalues: {
            $push: {
                k: "$arrayofkeyvalue.k",
                v: "$arrayofkeyvalue.v"
            }
        }
    }
}
 

что возвращает тот же результат.

Пожалуйста, обратите внимание, что arrayofkeyvalue это объект, так как вы запускали $unwind его до $group

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

Ответ №2:

Ошибка пользователя: неизвестный оператор группы «$карта»

Вы не можете использовать $map оператор на $group этапе непосредственно на корневом уровне,

вы можете попробовать добавить еще один групповой этап,

  • $group по k (ключу) и получите первое v (значение)
  • $group по null и постройте массив пары ключ-значение
  • $arrayToObject преобразование массива пар ключ-значение в объект
 db.collection(coll.name).aggregate([
  { $project: { arrayofkeyvalue: { $objectToArray: "$ROOT" } } },
  { $unwind: "$arrayofkeyvalue" },
  {
    $group: {
      _id: "$arrayofkeyvalue.k",
      value: { $first: "$arrayofkeyvalue.v" }
    }
  },
  {
    $group: {
      _id: null,
      allkeysandvalues: { $push: { k: "$_id", v: "$value" } }
    }
  },
  { $project: { allkeysandvalues: { $arrayToObject: "$allkeysandvalues" } } }
])
 

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

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

1. Оба ответа были одинаковыми и правильными. Я должен был выбрать один из них в качестве правильного ответа и выбрал тот, который пришел быстрее. Я все еще благодарен вам за краткое объяснение. Спасибо!