1

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?

1 Answer 1

1

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]
Sign up to request clarification or add additional context in comments.

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.