1

Having a rough time trying to get this query correct. I need to match against a string that is coming through as params from express. The problem is that it can be a string value or an ObjectId. True problem is that Mongoose doesn't cast strings to ObjectId's automatically, so I have to do that part. Here's what I have so far:

{
    $match: {
        $or: [
            {
                slug: data.product,
            },
            {
                _id: mongoose.Types.ObjectId.isValid(data.product)
                    ? [mongoose.Types.ObjectId(data.product)]
                    : [],
            },
        ],
    },
},
  1. /products/:product is my route
  2. /products/stream works
  3. /products/5cf4530c1b5c884fbf2298e5 fails

My full aggregation pipeline looks like this:

[
    {
        $match: {
            $or: [
                {
                    slug: data.product,
                },
                {
                    _id: mongoose.Types.ObjectId.isValid(data.product)
                        ? [mongoose.Types.ObjectId(data.product)]
                        : [],
                },
            ],
        },
    },
    {
        $lookup: {
            from: 'products',
            localField: '_id',
            foreignField: '_id',
            as: 'product',
        },
    },
    {
        $lookup: {
            from: 'ratings',
            localField: '_id',
            foreignField: 'product',
            as: 'rating',
        },
    },
    {
        $lookup: {
            from: 'categories',
            localField: 'categories',
            foreignField: '_id',
            as: 'category',
        },
    },
    {
        $unwind: {
            path: '$rating',
            preserveNullAndEmptyArrays: true,
        },
    },
    {
        $unwind: {
            path: '$product',
            preserveNullAndEmptyArrays: true,
        },
    },
    {
        $unwind: {
            path: '$category',
            preserveNullAndEmptyArrays: true,
        },
    },
    {
        $group: {
            _id: '$product._id',
            product: {
                $first: {
                    _id: '$product._id',
                    name: '$product.name',
                    url: '$product.url',
                    slug: '$product.slug',
                    logo: '$product.logo',
                    tagline: '$product.tagline',
                    description: '$product.description',
                    images: '$product.images',
                    roles: '$product.roles',
                    updated: '$product.updatedAt',
                    created: '$product.createdAt',
                },
            },
            categories: {
                $addToSet: {
                    _id: '$category._id',
                    name: '$category.name',
                    image: '$category.image',
                },
            },
            ratings: {
                $first: {
                    total: {
                        $sum: 1,
                    },
                    score: {
                        $sum: '$rating.rating',
                    },
                    sentiment: {
                        $sum: '$rating.sentiment',
                    },
                },
            },
        },
    },
]

Any thoughts? The docs aren't helping me out much. Thanks in advance!

Nick Parsons
  • 8,377
  • 13
  • 48
  • 70
  • 1
    Problem is here `{ _id: mongoose.Types.ObjectId.isValid(data.product) ? [mongoose.Types.ObjectId(data.product)] : [], },` You are comparing `_id` with array which you should not. Simple try with `_id: mongoose.Types.ObjectId(...)` – Ashh Jun 04 '19 at 12:16
  • Thanks @Fanpark! I have no idea how I missed that one. Problem solved! – Nick Parsons Jun 04 '19 at 13:13

0 Answers0