skip to Main Content

I have a dataset in MongoDB that contains array data for each state, each of which has it’s own inner array of zip codes. Here is a simplified example of the structure:

[
  {
    data: { 
      name: 'Alabama',
      zip_codes: [
        {
          id: 00000,
          population: 10
        },
        {
          id: 00001,
          population: 20,
        },
        ...
      ]
    }
  },
  {
    data: {
      name: 'Alaska',
      zip_codes: [
        {
          id: 10000,
          population: 5,
        },
        ...
      ]
    }
  }
  ...
]

My objective is to create a MongoDB view of just the zip code data. I want this (retaining the order from the original document):

zip_codes: [
  {
    id: 00000,
    population: 10
  },
  {
    id: 00001,
    population: 20,
  },
  {
    id: 10000,
    population: 5,
  },
  ...
]

I’m fairly new to MongoDB and am looking at the aggregation pipeline, particularly group and projection operations so far, but have not quite come across a way to do this. To all the Mongo experts out there, is there a pipeline I can build that will accomplish this?

I’ve tried $match and $project stages but couldn’t quite find something for this problem. I feel like this is solvable with Mongo but I’m too inexperienced. Any pointers in the right direction are greatly appreciated.

2

Answers


  1. You just need to $unwind the array, then you need to $group by $push each array into a single one and, as it seems in your case you don’t want an _id, then you can hide in the $project. This will return only one object with the zip_codes array. The aggregation goes as it follows:

    db.collection.aggregate([
        {
            $unwind: "$data.zip_codes"
        },
        {
            $group: {
                _id: null,
                zip_codes: { $push: "$data.zip_codes" },
            }
        },
        {
            $project: { 
                _id: 0, 
                zip_codes: 1 
            }
        },
    ])
    
    Login or Signup to reply.
  2. Simply $unwind the data.zip_codes field. $replaceRoot with the object to make it as the root document. The order of the documents will remain intact as long as you do not perform any sorting.

    db.runCommand( { create: "zipCodeView", viewOn: "zipCodes", pipeline: [
      {
        "$unwind": "$data.zip_codes"
      },
      {
        "$replaceRoot": {
          "newRoot": "$data.zip_codes"
        }
      }
    ]} )
    

    Mongo Playground


    Your expected output does not indicate clearly that do you want to put all the subdocuments into an array, but I will against that idea, since that may breach MongoDB 16MB document size limit if the total count of documents is large.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search