mongodb

Best Mongo Aggregation to Map Array of _ids in One Collection To Values from Another


I have two related mongo collections. These example documents illustrate their relation:

// "things" collection example document:
{
  _id: 1,
  categories: [123, 234],
  // other fields
}

// "categories" collection example documents:
{
  _id: 123,
  value: "Category name"
},
{
  _id: 234,
  value: "Other category name"
}

I've been trying to find a way to map the id numbers in the categories array of a document from things to the values from the corresponding documents in the categories collection. Per the above example, you would end up with this document:

{
  _id: 1,
  categories: [
    "Category name",
    "Other category name",
  ],
  // other fields
}

My problem is that my current pipeline is overly-complicated and surely performing unnecessary operations, creating potential performance issues. My current pipeline is:

{
  _id: 1,
  categories: [123, 234],
  // other fields
}
{
  _id: 1,
  categories: 123,
  // other fields
},
{
  _id: 1,
  categories: 234,
  // other fields
}
{
  _id: 1,
  categories: [{ _id: 123, value: "Category name" }],
  // other fields
},
{
  _id: 1,
  categories: [{ _id: 234, value: "Other category name" }],
  // other fields
}
{
  _id: 1,
  categories: { _id: 123, value: "Category name" },
  // other fields
},
{
  _id: 1,
  categories: { _id: 234, value: "Other category name" },
  // other fields
}
{
  _id: 1,
  categories: "Category name",
  // other fields
},
{
  _id: 1,
  categories: "Other category name",
  // other fields
}
{
  _id: 1,
  categories: [
    "Category name",
    "Other category name",
  ],
  // other fields
}

I'm worried I'm missing aggregate functions that are much more efficient and thus creating slow and costly read operations when I use this on a large number of documents in the future but I'm failing to find cleaner solutions. Any nudge in the right direction would be highly appreciated.


Solution

  • per @cmgchess -

    This can all be done in two steps:

    {
      _id: 1,
      categories: [123, 234],
      // other fields
    }
    
    {
      _id: 1,
      categories: [
        {
          _id: 123,
          value: "Category name"
        },
        {
          _id: 234,
          value: "Other category name"
        }
      ],
      // other fields
    }
    
    // operation:
    {
      $set: {
        categories: {
          $map: {
            input: "$categories",
            as: "category",
            in: "$$category.value"
          }
        }
      }
    }
    
    // result:
    {
      _id: 1,
      categories: [
        "Category name",
        "Other category name"
      ],
      // other fields
    }
    

    paydirt. :)