Acontece que a conversão do ObjectId parecia ser o problema. Precisamos usar
mongoose.Types.ObjectId
O código da API ficará assim
getProductByProductId: function (productId) {
return new Promise((resolve, reject) => {
User.aggregate([
{
$match: {
"shops.products._id": mongoose.Types.ObjectId(productId)
}
},
{
"$unwind": "$shops"
},
{
"$unwind": "$shops.products"
},
{
$match: {
"shops.products._id": mongoose.Types.ObjectId(productId)
}
},
{
$project: {
"_id": "$shops.products._id",
"title": "$shops.products.title"
}
}
])
.then(products => {
resolve(products)
}).catch(err => {
reject(err);
});
});
}