DEV Community

Cover image for Mastering The Database - Accessing Nested Records - Series #10
Functional Javascript
Functional Javascript

Posted on

2

Mastering The Database - Accessing Nested Records - Series #10

Intro

In the last series we retrieved a random sample of docs.
It was very simple. Essentially a oneliner.

But supposes we wanted to select a random sample of items that existed as subdocs of the outer level docs in our app?

Actually, it's not too hard.
And we don't use any loops.
Instead we "unwind", or your could think of it as "flattening" our arr of docs.

If an artist has an arr of albums, then each artist doc has an arr of subdocs.

If an artist's arr of albums each contain an arr of song, then we have a doc that has an arr of subdocs whose subdocs also have an arr of subdocs.

Here is what the outer doc's data shape look like:

/*
data shape:
 {
    "artist": "Julian Lennon",
    "albums": [
      {
        "albumTitle": "Valotte (1984)",
        "albumSongs": [
          {
            "song": "Valotte"
          },
          {
            "song": "O.K. for You"
          },
          {
            "song": "On the Phone"
//....
*/
Enter fullscreen mode Exit fullscreen mode

Here is the query to select a random set of song (in this case 5 of them)

  mgArr(dbEnum.nlpdb, collEnum.songsColl,
    unwindArr("albums"),
    unwindArr("albums.albumSongs"),
    randomSample(5),
    projectIncludeNoId("artist", "albums.albumSongs.song"),
  )
Enter fullscreen mode Exit fullscreen mode

Here are five random songs.
We've included the artist so we can see who the song is performed by:

/*
output:

[
  {
    "artist": "Miley Cyrus",
    "albums": {
      "albumSongs": {
        "song": "Girls Just Wanna Have Fun"
      }
    }
  },
  {
    "artist": "Creedence Clearwater Revival",
    "albums": {
      "albumSongs": {
        "song": "Penthouse Pauper"
      }
    }
  },
  {
    "artist": "Judas Priest",
    "albums": {
      "albumSongs": {
        "song": "Out In The Cold"
      }
    }
  },
  {
    "artist": "Akon",
    "albums": {
      "albumSongs": {
        "song": "Throw Dat"
      }
    }
  },
  {
    "artist": "Nazareth",
    "albums": {
      "albumSongs": {
        "song": "Hit The Fan"
      }
    }
  }
]
*/

Enter fullscreen mode Exit fullscreen mode

Notes

1.
The unwindArr is a wrapper func around the $unwind stage operator.
The wrappers make the code look cleaner, and they're usually oneliners:

export const unwindArr = k => ({ $unwind: "$" + k });
Enter fullscreen mode Exit fullscreen mode

2.
We have to unwind the outer arr, then we can next unwind the inner arr. We could keep on going if there were more arrs. For example, each song could have an arr of songwriters.

3.
Once all the songs are unwound, we can grab a random sample of them using the $sample stage operator.
The RandomSample wrapper is a simple oneliner:

export const randomSample = lim => ({ $sample: { size: lim } });
Enter fullscreen mode Exit fullscreen mode

4.
Notice the dot notation in the unwind func in order to express the path to the nest arrs.

5.
Finally, for ease of display reason, I "project" out only two fields. My wrapper func, the "NoId" variant, excludes the Primary Key. I use this variant just for testing
The raw $project syntax would look like this (0 means exclude, 1 means include):

{ $project: { _id: 0, artist: 1, "albums.albumSongs.song": 1 } },
Enter fullscreen mode Exit fullscreen mode

6.
Take note also, that conveniently, we can swap out and use either the wrapper funcs, or the raw MongoDB stage syntax with our call to the MongoDB aggregate func. This is because the wrapper funcs simply just returns the raw syntax anyhow, of each stage in the pipeline.

Resources

https://docs.mongodb.com/manual/reference/operator/aggregation/unwind

https://docs.mongodb.com/manual/reference/operator/aggregation/sample

AWS Q Developer image

Build your favorite retro game with Amazon Q Developer CLI in the Challenge & win a T-shirt!

Feeling nostalgic? Build Games Challenge is your chance to recreate your favorite retro arcade style game using Amazon Q Developer’s agentic coding experience in the command line interface, Q Developer CLI.

Participate Now

Top comments (0)

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

👋 Kindness is contagious

Explore this insightful write-up embraced by the inclusive DEV Community. Tech enthusiasts of all skill levels can contribute insights and expand our shared knowledge.

Spreading a simple "thank you" uplifts creators—let them know your thoughts in the discussion below!

At DEV, collaborative learning fuels growth and forges stronger connections. If this piece resonated with you, a brief note of thanks goes a long way.

Okay