2

I need to analyze some mongo db collections. What I need to extract the names and values of a collection.

Heres's how far I got:

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

This works quite nicely. I get all the keys. However I'd like to get the values too.

So, I thought "piece o' cake" and replaced the allkeys section with the allkeysandvalues section, which is supposed to create a map with key and value pairs.

Like this:

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();

But that's not working. I get the error message

MongoError: unknown group operator '$map'

Does anyone know hot to solve this?

1

2 Answers 2

4

The $group pipeline stage requires accumulator expression so you have to use $push instead of $map:

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

or

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

which returns the same result.

Please note that arrayofkeyvalue is an object since you run $unwind prior to $group

Mongo Playground

Sign up to request clarification or add additional context in comments.

Comments

3

MongoError: unknown group operator '$map'

You can not use $map operator in $group stage directly in root level,

you can try adding one more group stage,

  • $group by k (key) and get the first v (value)
  • $group by null and construct the array of key-value pair
  • $arrayToObject convert key-value pair array to object
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" } } }
])

Playground

1 Comment

Both answers were similar and correct. I had to choose one as the correct answer and chose the one, which came in faster. I am still grateful for your concise explanation. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.