How to lookup a field in an array of subdocuments in mongoose?

与世无争的帅哥 提交于 2020-04-18 05:47:25

问题


I have an array of review objects like this :

   "reviews": {
        "author": "5e9167c5303a530023bcae42",
        "rate": 5,
        "spoiler": false,
        "content": "This is a comment This is a comment This is a comment.",
        "createdAt": "2020-04-12T16:08:34.966Z",
        "updatedAt": "2020-04-12T16:08:34.966Z"
    },

What I want to achieve is to lookup the author field and get the user data, but the problem is that the lookup I am trying to use only returns this to me:

Code :

 .lookup({
    from: 'users',
    localField: 'reviews.author',
    foreignField: '_id',
    as: 'reviews.author',
  })

Response :

Any way to get the author's data in that field? That's where the author's Id is.


回答1:


Try to execute below query on your database :

db.reviews.aggregate([
  /** unwind in general is not needed for `$lookup` for if you wanted to match lookup result with specific elem in array is needed */
  {
    $unwind: { path: "$reviews", preserveNullAndEmptyArrays: true },
  },
  {
    $lookup: {
      from: "users",
      localField: "reviews.author",
      foreignField: "_id",
      as: "author", // Pull lookup result into 'author' field
    },
  },
  /** Update 'reviews.author' field in 'reviews' object by checking if   'author' field got a match from 'users' collection.
   * If Yes - As lookup returns an array get first elem & assign(As there will be only one element returned -uniques),
   * If No - keep 'reviews.author' as is */
  {
    $addFields: {
      "reviews.author": {
        $cond: [
          { $ne: ["$author", []] },
          { $arrayElemAt: ["$author", 0] },
          "$reviews.author",
        ],
      },
    },
  },
  /** Group back the documents based on '_id' field & push back all individual 'reviews' objects to 'reviews' array */
  {
    $group: {
      _id: "$_id",
      reviews: { $push: "$reviews" },
    },
  },
]);

Test : MongoDB-Playground

Note : Just in case if you've other fields in document along with reviews that needs to be preserved in output then starting at $group use these stages :

  {
    $group: {
      _id: "$_id",
      data: {
        $first: "$$ROOT"
      },
      reviews: {
        $push: "$reviews"
      }
    }
  },
  {
    $addFields: {
      "data.reviews": "$reviews"
    }
  },
  {
    $project: {
      "data.author": 0
    }
  },
  {
    $replaceRoot: {
      newRoot: "$data"
    }
  }

Test : MongoDB-Playground

Note : Try to keep queries to run on lesser datasets maybe by adding $match as first stage to filter documents & also have proper indexes.




回答2:


you should use populate('author') method of mongoose on the request to the server which gets the id of that author and adds the user data to the response of mongoose and dont forget to set your schema in a way that these two collections are connected in your review schema you should add ref to the schema which the author user is saved author: { type: Schema.Types.ObjectId, ref: 'users' },




回答3:


You can follow this code

$lookup:{
            from:'users',
            localField:'reviews.author',
            foreignField:'_id',
            as:'reviews.author'
        }
**OR**

> When You find the doc then use populate
> reviews.find().populate("author")




来源:https://stackoverflow.com/questions/61177323/how-to-lookup-a-field-in-an-array-of-subdocuments-in-mongoose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!