Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create MongoDB fields with names based on sub-document values using aggregation pipeline?

Given a MongoDB collection with the following document structure:

{
    array_of_subdocs:
         [
             {
                 animal: "cat",
                 count: 10
             },
             {
                 animal: "dog",
                 count: 20
             },

             ...
         ]
}

where each document contains an array of sub-documents, I want transform the collection into documents of the structure:

{
    cat: { count: 10 },
    dog: { count: 20 },
    ...
}

where each sub-document is now the value of a new field in the main document named after one of the values within the sub-document (in the example, the values of the animal field is used to create the name of the new fields, i.e. cat and dog).

I know how to do this with eval with a Javascript snippet. It's slow. My question is: how can this be done using the aggregation pipeline?

like image 472
Ghopper21 Avatar asked Aug 17 '14 22:08

Ghopper21


People also ask

What passes through a MongoDB aggregation pipeline?

An aggregation pipeline consists of one or more stages that process documents: Each stage performs an operation on the input documents. For example, a stage can filter documents, group documents, and calculate values. The documents that are output from a stage are passed to the next stage.

Which aggregation pipeline stage reshapes each document in the stream such as by adding new fields or removing existing fields?

Similar to $project , $set reshapes each document in the stream; specifically, by adding new fields to output documents that contain both the existing fields from the input documents and the newly added fields. $set is an alias for $addFields stage.

Which aggregation method is preferred for use by MongoDB?

The pipeline provides efficient data aggregation using native operations within MongoDB, and is the preferred method for data aggregation in MongoDB. The aggregation pipeline can operate on a sharded collection. The aggregation pipeline can use indexes to improve its performance during some of its stages.

What aggregation option is used to specify the specific fields that needs to be passed to the next stage of the aggregation pipeline?

The following aggregation option is used to specify the specific fields that needs to be passed to the next stage of the aggregation pipeline: Answer : $project.


1 Answers

According to this feature request and its solution, the new feature will be added for this functionality - Function called arrayToObject.

db.foo.aggregate([
  {$project: {
    array_of_subdocs: {
      $arrayToObject: {
        $map: {
          input: "$array_of_subdocs",
          as: "pair",
          in: ["$$pair.animal", "$$pair.count"]
        }
      }
    }
  }}
])

But at the moment, no solution. I suggest you to change your data structure. As far as I see there are many feature requests labeled as Major but not done for years.

like image 72
Tolga Evcimen Avatar answered Oct 20 '22 08:10

Tolga Evcimen