Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to merge JSON objects based on key/value pair?

I need to combine results from two different documents in Mongo. I have a function like this:

async function getReviewsByUserId (req, res) {
  const { userId } = req.params

  const reviews = await Review.find({ userId }).lean() || []

  return res.status(200).send(reviews.reverse())
}

The reviews array looks like this:

{
    "_id" : ObjectId("1263b55ef2cdd3ebb0654d1dd"),
    "launchId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03111",
    "userId" : "1",
}
{
    "_id" : ObjectId("6355565cf5ef2cddebb065584"),
    "launchId" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "userId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03112",
}

I need to use the launchId from each review, look up a launch object from my mongo database, and combine that with the correct object in the reviews array.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Example of what I mean:

async function getReviewsByUserId (req, res) {
  const { userId } = req.params

  const reviews = await Review.find({ userId }).lean() || []

  const launches = await Launch.find(/* find all launches where launch._id is equal to reviews.launchId*/)

  return res.status(200).send(launches.reverse())
}

So if launches data looks like this (and launches is also an array of ALL launches):

{
    "_id" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "name" : "The Park",
}

Then how can I merge this with the reviews payload where the launch._id == reviews.launchId so that the final data looks like this:

{
    "_id" : ObjectId("1263b55ef2cdd3ebb0654d1dd"),
    "launchId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03111",
    "userId" : "1",
}
{
    "_id" : ObjectId("6355565cf5ef2cddebb065584"),
    "launchId" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "userId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03112",
    "launch": {
        "_id" : "12b53940-136f-3399-aaed-fe9d0dc05473",
        "name" : "The Park",
    }
}

>Solution :

This could be achieved by using aggregate pipelines.

  1. Filter reviews by userId in $match stage
  2. $lookup for launches
  3. $unwind the launch array to an object

The solution could be:

  async function getReviewsByUserId(req, res) {
    const { userId } = req.params;

    const launches = await Review.aggregate([
      {
        $match: {
          userId
        }
      },
      {
        $lookup: {
          from: "launches",
          localField: "launchId",
          foreignField: "_id",
          as: "launch"
        }
      },
      {
        $unwind: {
          path: "$launch",
          preserveNullAndEmptyArrays: true
        }
      }
    ]);

    return res.status(200).send(launches.reverse());
  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading