Home > Net >  How to combine findOne (in array) with aggregate in Mongo?
How to combine findOne (in array) with aggregate in Mongo?

Time:10-04

I currently have a mongo query that looks like this:

  const user = await User.findOne({ userId }).lean() || []

  const contributions = await Launch.aggregate([
    { $sort: { addedAt: -1 } },
    { $limit: 10 },
    {
      $match: {
        _id: { $in: user.contributions }
      }
    },
    {
      $addFields: {
        activity: 'contribution',
        launchName: '$name',
        launchId: '$_id',
        date: '$addedAt',
        content: '$description'
      }
    }
  ])

But instead of having two different mongo queries (the findOne and aggregate), how can I combine it into one query?

I tried this but it just errors out immediately in the lookup part:

  const contributions = await Launch.aggregate([
    { $sort: { addedAt: -1 } },
    { $limit: 10 },
    {
      $lookup: {
        from: 'user',
        let: { id: $user.contributions },
        pipeline: [
          { $match: { $expr: { $in: [$_id, $$user.contributions] } } }
        ],
        localField: '_id',
        foreignField: 'userId',
        as: 'user'
      }
    },
    {
      $addFields: {
        activity: 'contribution',
        launchName: '$name',
        launchId: '$_id',
        date: '$addedAt',
        content: '$description'
      }
    }
  ])

I've never used the pipeline option so a little confused on how to fix this problem?

CodePudding user response:

  1. Enclose these $user.contributions, $_id with quotes in order to make the query valid.

  2. Since you declare the id variable with the value of user.contributions. You should use the variable with $$id instead of $$user.contributions.

  3. I don't think the localField and foreignField are needed as you are mapping/joining with pipeline.

Your aggregation query should be looked as below:

const contributions = await Launch.aggregate([
  { $sort: { addedAt: -1 } },
  { $limit: 10 },
  {
    $lookup: {
      from: 'user',
      let: { id: "$user.contributions" },
      pipeline: [
        { $match: { $expr: { $in: ["$_id", "$$id"] } } }
      ],
      as: 'user'
    }
  },
  {
    $addFields: {
      activity: 'contribution',
      launchName: '$name',
      launchId: '$_id',
      date: '$addedAt',
      content: '$description'
    }
  }
])
  • Related