Home > OS >  How can I get only the array element as output instead of whole object in MongoDB?
How can I get only the array element as output instead of whole object in MongoDB?

Time:10-26

Below is my code to display review array data which is part of the restaurant collection object:

async get(reviewId) {
    const restaurantsCollection = await restaurants();
    reviewId = ObjectId(reviewId)
  
    const r = await restaurantsCollection.findOne(
      { reviews: { $elemMatch: { _id : reviewId } } },
      {"projection" : { "reviews.$": true }}
    )
  
    return r
  }

My object looks like:

{
  _id: '6176e58679a981181d94dfaf',
  name: 'The Blue Hotel',
  location: 'Noon city, New York',
  phoneNumber: '122-536-7890',
  website: 'http://www.bluehotel.com',
  priceRange: '$$$',
  cuisines: [ 'Mexican', 'Italian' ],
  overallRating: 0,
  serviceOptions: { dineIn: true, takeOut: true, delivery: true },
  reviews: []
}

My output looks like:

{
    "_id": "6174cfb953edbe9dc5054f99", // restaurant Id
    "reviews": [
        {
            "_id": "6176df77d4639898b0c155f0", // review Id
            "title": "This place was great!",
            "reviewer": "scaredycat",
            "rating": 5,
            "dateOfReview": "10/13/2021",
            "review": "This place was great! the staff is top notch and the food was delicious!  They really know how to treat their customers"
        }
    ]
}

What I want as output:

{
    "_id": "6176df77d4639898b0c155f0",
    "title": "This place was great!",
    "reviewer": "scaredycat",
    "rating": 5,
    "dateOfReview": "10/13/2021",
    "review": "This place was great! the staff is top notch and the food was delicious!  They really know how to treat their customers"
}

How can I get the output as only the review without getting the restaurant ID or the whole object?

CodePudding user response:

So the query operators, find and findOne do not allow "advanced" restructure of data.

So you have 2 alternatives:

  1. The more common approach will be to do this in code, usually people either use some thing mongoose post trigger or have some kind of "shared" function that handles all of these transformations, this is how you avoid code duplication.

  2. Use the aggregation framework, like so:

const r = await restaurantsCollection.aggregate([
    {
        $match: { reviews: { $elemMatch: { _id : reviewId } } },
    },
    {
        $replaceRoot: {
            newRoot: {
                $arrayElemAt: [
                    {
                        $filter: {
                            input: "$reviews",
                            as: "review",
                            cond: {$eq: ["$$review._id", reviewId]}
                        }
                    },
                    0
                ]
            }
        }
    }
])
return r[0]
  • Related