Fetching array counts with Mongoose

Fetching array counts with Mongoose

As a side project, I am working on a Pinterest clone of sorts. It's a simplified, scaled down version and the purpose of the project is for me to get better at React and Node.js.

I've been using MongoDb to store all my data, and Mongoose for object modelling and querying. Coming from a .Net and MSSQL background, there has been a few small bumps in the road along the way.

One of these bumps has been getting the count of an array in an Object. Let's start by taking a look at what my schema looks like:

const boardSchema = new Schema({
  name: String,
  pins: [
    {
      link: String,
      title: String,
    },
  ],
});

As you can see, each board has a name and an array of pins. Now, on my home page, I want to display the number of pins for each board, like this:

pins.png

One way to do this would be to fetch the entire array of pins for each board, and simply check pins.length. That might work fine in this example, where there are only three pins and each pin contains very little data. But what if there are thousands of pins, or we start adding more data to each pin? It would be unnecessary to fetch all the pins and all the data, just to get the count.

To do this in a more efficient way, we use aggregate() and project():

let boards = await Board.aggregate()
  .project({
    name: 1,
    pinsCount: { $size: "$pins" },
  })
  .exec();

project() allows us to pass on existing fields and/or create new, computed fields in the aggregation pipeline. In this case, we are passing along name by setting the value to 1. If we didn't want the name, we would leave it out or set it to 0.

Then, we are creating a new field called pinsCount, and computing the value by getting the $size of the $pins array.

In the end, boards[] will look something like this:

[{
    "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "Recipes",
    "pinsCount": 3,
}]

_id is always included, unless we explicitly exclude it

Cover photo by David Wright on Unsplash