mongodbmongooseaggregation-frameworkaggregation

$unset operator turns a simple object into array


I have a Project entity (projects collection). Each Project belongs to an organization represented by Project.orgId and has an author Project.author taken from users collection.

I want to query the projects that belong to an organization using Mongoose, and here's the pipeline I came up with:

Project.aggregate([
  {
    $match: { organization: new mongoose.Types.ObjectId("an-object-id") }
  },
  {
    $lookup: {
      from: User.collection.collectionName,
      localField: "authorId",
      foreignField: "_id",
      as: "author",
    },
    /* Tried moving unset here. Doesn't work. Error: Arguments must be aggregate pipeline operators
    {
      "$unset": ["__v", "hash"],
    },
    */      
  },
  {
    $unset: ["author.__v", "author.hash"]
  }
])

The problem with this pipeline, is that instead of project.author being an object, it turns into a single-element array.

Expected

{
  "codename": "Longhorn",
  "launch": 1970-01-01T00:00:00Z,
  "author": {
    "firstName": "John",
    "lastName": "Smith"
  }
}

Actual

{
  "codename": "Longhorn",
  "launch": 1970-01-01T00:00:00Z,
  "author": [
    {
      "firstName": "John",
      "lastName": "Smith"
    }
  ]
}

What is the proper pipeline?


Solution

  • To deconstruct the array into multiple documents, you need the $unwind stage:

    Project.aggregate([
      {
        $match: { organization: new mongoose.Types.ObjectId("an-object-id") }
      },
      {
        $lookup: {
          from: User.collection.collectionName,
          localField: "authorId",
          foreignField: "_id",
          as: "author",
        }
      },
      {
        $unwind: "$author",
      },
      {
        $unset: ["author.__v", "author.hash"]
      }
    ])