1

If I have a controller like this:

const Review = require('../models/review')
const Launch = require('../models/launch')

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

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

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

How can I use the returned reviews to query more objects in the fastest way possible? Example of what I mean:

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

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

  let launches = []
  for (review in reviews) {
    let launch = await Launch.find({launchId: review.launchId})
    launches.push(launch)
  }

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

So as you can see, I simply loop though all my reviews and then use the review.launchId to lookup launches and push each to an array and return that.

Is this efficient? Is there a faster way to accomplish the same thing?

1
  • 1
    @Tiago Bértolo's answer seems good. Alternatively consider combining the two find()s into a single aggregate() that uses $lookup. Commented Sep 30, 2022 at 16:21

2 Answers 2

1

You can use the operator $in to find multiple elements by launchId.

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

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

  let launches = []
  const reviewLaunchIds = reviews.map(review => review.launchId)
  let launch = await Launch.find({launchId:{ $in: reviewLaunchIds })

  return res.status(200).send(launch)
}
Sign up to request clarification or add additional context in comments.

Comments

0

Using aggregate pipelines would be faster and more efficient but a little complicated to use.

The query could be achieved by:

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

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.