简体   繁体   中英

Mongoose query works in find() but not in aggregation match

MongoDb Query is working fine in countDocuments but not in aggregation $match , below is code

  let query = [];
  let sort = { createdAt: 1 };

  const page = req.body.page || 1;
  const limit = req.body.limit || 10;
  let skip = (page - 1) * limit

  if (!_.isEmpty(req.body.search)) {
    query.push({
      "name": {
        $regex: req.body.search, $options: "i",
      }
    })
  }

  if (!_.isUndefined(req.body.featured)) {
    query.push({ "featured": req.body.featured });
  }
  if (!_.isUndefined(req.body.todays_deal)) {
    query.push({ "todays_deal": req.body.todays_deal });
  }


 if (req.body.subcategory_id && Array.isArray(req.body.subcategory_id)) {
    query.push({ "subCategory_id": { "$in": req.body.subcategory_id } })
  }

  if (!_.isEmpty(req.body.brand_id) && _.isArray(req.body.brand_id)) {
    query.push({ "brand_id": { "$in": req.body.brand_id } });
  }

  if (!_.isEmpty(req.body.size) && _.isArray(req.body.size)) {
    query.push({ "variants.size": { "$in": req.body.size } });
  }

  if (!_.isEmpty(req.body.color) && _.isArray(req.body.color)) {
    query.push({ "variants.color": { "$in": req.body.color } });
  }

  if (!_.isEmpty(req.body.tags) && _.isArray(req.body.tags)) {
    query.push({ "tags": { "$in": req.body.tags } });
  }

  if (req.body.price) {
    query.push({
      "price": {
        $gte: req.body.price.minimum, $lte: req.body.price.maximum
      }
    })
  }

  if (!_.isEmpty(req.body.sort_by)) {
    switch (req.body.sort_by) {
      case "newest":
        sort = { createdAt: -1 };
        break;
      case "oldest":
        sort = { createdAt: 1 };
        break;
      case "price_low_to_high":
        sort = { "variants.price": 1 };
        break;
      case "price_high_to_low":
        sort = { "variants.price": -1 };
        break;
      default:
        return res.status(404).json({ msg: "Invalid sort value" });
    }
  }

  try {
    const productCount = await Product.countDocuments({ $and: query });
    let allProducts = await Product.aggregate([
      { "$match": { $and: query } },
      { "$sort": {  _id: -1 } },
      {
        $project: {
          modal_name: 0,
          manufactured_by: 0,
          manufacturing_country: 0,
          stock_visible: 0,
          cash_on_delivery: 0,
          featured: 0,
          todays_deal: 0,
          publish: 0,
          created_by: 0,
          created_by_id: 0,
          unit: 0,
          variants_image: 0,
          minimum_purchase_quantity: 0
        }
      },
      { $facet: { product: [{$skip: skip},{ $limit: limit }]}},
      { $unwind: "$product" }
    ])

    // .find({ $and: query }).select({
    //   modal_name: 0,
    //   manufactured_by: 0,
    //   manufacturing_country: 0,
    //   stock_visible: 0,
    //   cash_on_delivery: 0,
    //   featured: 0,
    //   todays_deal: 0,
    //   publish: 0,
    //   created_by: 0,
    //   created_by_id: 0,
    //   unit: 0,
    //   variants_image: 0,
    //   minimum_purchase_quantity: 0
    // }).populate({
    //   path: 'category_id',
    //   model: 'Category',
    //   select: { '_id': 1, 'name': 1 }
    // })
    //   .skip(skip)
    //   .limit(limit)
    //   .sort(sort)
    //   .select("-__v")
    //   .lean();

    /* .aggregate([
    { "$match": { $or: query } },
    { "$sort": sort },
    {
      $project: 
    },
    { $facet: { product: [{ $skip: skip }, { $limit: limit }] } },
    { $unwind: '$product' }
  ]) */

    let result = response.OK
    result.data = {
      products: allProducts,
      info: {
        totalNumber: productCount,
        hasNextPage: limit * page < productCount,
        hasPreviousPage: page > 1,
        nextPage: page + 1,
        previousPage: page - 1,
        lastPage: Math.ceil(productCount / limit),
      },
    }

    return res.status(200).send(successRes(result, res.statusCode));
  } catch (error) {
    console.log("Server Error in product.getProducts", error);
    return res.status(500).send(errorsRes(response.SERVER_ERROR, res.statusCode));
  }

Count returns 40 items while aggregate is returning null array below is query there can be multiple objects.

[
  {
    "$or": [
      {
        "category_id": {
          "$in": [
            "6214fea736df45237c39ca65"
          ]
        }
      },
      {
        "subCategory_id": {
          "$in": [
            "6214fea736df45237c39ca65"
          ]
        }
      }
    ]
  },
{ "brand_id": { "$in": ["6214fea736df45237c78979"] } }
]

And also above query works fine with find() query

   .find({ $and: query })
    .select({
      modal_name: 0,
      manufactured_by: 0,
      manufacturing_country: 0,
      stock_visible: 0,
      cash_on_delivery: 0,
      featured: 0,
      todays_deal: 0,
      publish: 0,
      created_by: 0,
      created_by_id: 0,
      unit: 0,
      variants_image: 0,
      minimum_purchase_quantity: 0
    })
      .skip(skip)
      .limit(limit)
      .sort(sort)
      .select("-__v")
      .lean();

UPDATE

{
   "_id":{
      "$oid":"62170046b58fab4938818a6f"
   },
   "brand_id":{
      "$oid":"6214feb936df45237c39cac1"
   },
   "tags":[
      "Nen?XfucBd",
      "M|b}vy`FY9",
      "vd>J^a[^mm",
      "34370",
      "X<\"QoWs##B",
      "}v6GsaDE\"e",
      "g^Q`:r\\/(}",
      "45884",
      "IYCN&LkI&,",
      "81259"
   ],
   "image":[
      "https://images.unsplash.com/photo-1493552152660-f915ab47ae9d?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0ODAz&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
      "https://images.unsplash.com/photo-1493552152660-f915ab47ae9d?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0ODEw&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
      "https://images.unsplash.com/photo-1432251407527-504a6b4174a2?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLG1lbnNmYXNoaW9ufHx8fHx8MTY0NTI4NDg4Mw&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920"
   ],
   "colors":[
      "#1b444e",
      "#134a77",
      "#1b6030"
   ],
   "variants_image":[
      {
         "color":"#1b444e",
         "img":[
            "https://images.unsplash.com/photo-1592265911347-2d381a17e161?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzYx&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1566955244976-483f8d7965e2?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzY2&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1590736945722-bf5c39bc6513?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzU1&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920"
         ]
      },
      {
         "color":"#134a77",
         "img":[
            "https://images.unsplash.com/photo-1592265911347-2d381a17e161?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzYx&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1566955244976-483f8d7965e2?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzY2&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1457968867385-9f877f3f2bce?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0NzY0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920"
         ]
      },
      {
         "color":"#1b6030",
         "img":[
            "https://images.unsplash.com/photo-1483959651481-dc75b89291f1?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLG1lbnNmYXNoaW9ufHx8fHx8MTY0NTI4NDg5MA&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1493552152660-f915ab47ae9d?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0ODEw&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920",
            "https://images.unsplash.com/photo-1498335746477-0c73d7353a07?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8d2FsbHBhcGVyLGZhc2hpb258fHx8fHwxNjQ1Mjg0Nzg0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1920"
         ]
      }
   ],
   "stock_visible":false,
   "cash_on_delivery":false,
   "featured":false,
   "todays_deal":false,
   "publish":false,
   "item_code":"403dbdf8-e2af-43ee-941d-0cac51347741",
   "name":"Awesome Rubber Computer",
   "slug":"intelligent-steel-pizza",
   "description":"Qui sapiente omnis illo delectus dolor libero. Ex temporibus quod omnis. Quas voluptates omnis culpa cum laboriosam alias dolor nesciunt id. Vel animi dolores eius autem deleniti quod enim nesciunt. Sed voluptatem suscipit consectetur quas. Voluptatem sint ipsam nulla iure dolores facilis id. Nihil occaecati natus ex nobis esse autem ullam. Ut velit dolorum id itaque consequatur ut beatae ut similique. Aperiam iusto qui et illo. Quisquam molestiae ad alias laudantium modi tempore commodi. Rem aut ut. Nihil voluptatem tenetur beatae consectetur. Consectetur odio numquam aut. Dicta mollitia nesciunt corrupti magni et. Dolores rerum quam ad ea numquam repudiandae aut ut. Aut accusamus explicabo et vel. Est quos adipisci dolor aliquam. Sapiente fuga dolor.",
   "modal_name":"Handmade Frozen Table",
   "manufactured_by":"Davis - Hegmann",
   "manufacturing_country":"Bermuda",
   "category_id":{
      "$oid":"6214fec536df45237c39cafe"
   },
   "subCategory_id":{
      "$oid":"6214fec636df45237c39cb00"
   },
   "unit":"8",
   "price":842,
   "stock":53,
   "discount":14,
   "special_price":724.12,
   "minimum_purchase_quantity":1,
   "product_video_url":"https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4",
   "variants":[
      {
         "_id":{
            "$oid":"62170046b58fab4938818a70"
         },
         "sku":"abe17cd2-642f-4267-b9fd-b6c34c31d799",
         "size":"s",
         "color":"#1b444e",
         "price":542,
         "discount":"29",
         "special_price":"384.82",
         "quantity":50
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a71"
         },
         "sku":"137cf6c5-df2f-4e22-ab9e-e2dec15b3630",
         "size":"m",
         "color":"#1b444e",
         "price":675,
         "discount":"22",
         "special_price":"526.50",
         "quantity":19
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a72"
         },
         "sku":"03179397-60a2-414b-acd4-af3916e374c1",
         "size":"l",
         "color":"#1b444e",
         "price":933,
         "discount":"20",
         "special_price":"746.40",
         "quantity":22
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a73"
         },
         "sku":"0f7c5e92-8aed-4308-92c7-e24ba4d8fd17",
         "size":"s",
         "color":"#134a77",
         "price":299,
         "discount":"12",
         "special_price":"263.12",
         "quantity":3
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a74"
         },
         "sku":"c824490c-f943-414a-91b1-15554fd21bd1",
         "size":"m",
         "color":"#134a77",
         "price":820,
         "discount":"23",
         "special_price":"631.40",
         "quantity":63
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a75"
         },
         "sku":"f487a863-13a8-43e7-b710-525db504af6a",
         "size":"l",
         "color":"#134a77",
         "price":265,
         "discount":"22",
         "special_price":"206.70",
         "quantity":49
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a76"
         },
         "sku":"d8c4d17b-626c-4440-951a-6bbceb8aae67",
         "size":"s",
         "color":"#1b6030",
         "price":953,
         "discount":"28",
         "special_price":"686.16",
         "quantity":28
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a77"
         },
         "sku":"a1780a1b-dc86-4391-83a6-20d5fa3a5bbb",
         "size":"m",
         "color":"#1b6030",
         "price":326,
         "discount":"27",
         "special_price":"237.98",
         "quantity":5
      },
      {
         "_id":{
            "$oid":"62170046b58fab4938818a78"
         },
         "sku":"318669fd-0637-46c7-8af4-b0ab3bbb6ca1",
         "size":"l",
         "color":"#1b6030",
         "price":519,
         "discount":"17",
         "special_price":"430.77",
         "quantity":55
      }
   ],
   "created_by":"Admin",
   "created_by_id":{
      "$oid":"62121e477f0690117d79b86d"
   },
   "createdAt":{
      "$date":"2022-02-24T03:49:26.410Z"
   },
   "updatedAt":{
      "$date":"2022-02-24T03:49:26.410Z"
   },
   "__v":0
}```

Thank you for the sample document.

I have made few assumptions & used your exact $match condition (query)

  • $skip : should be 0 for the first query and only when the page size exceeds, the skip value will be greater than 0 for the further extractions. This could be the cause of issue if value had been greater than 0 for the first extraction.
  • $limit : for now I have assigned as 10
  • $sort : this could be any, it would not be the cause of issue. for now, i have sorted with _id desc

The aggregate returns multiple documents and each will have the product field since we have used $facet .

MongoDB Playground: https://mongoplayground.net/p/LguFlH541QJ

Let me know if it helps. If the issue persists, you can provide MongoDB Playground link or more documents for me to look at.

UPDATE

The only difference I see between countDocuments and aggregate is the $skip & $limit part. If the req.body.page is undefined or 1, it should work fine.

You can adjust the aggregate without using $facet also. Revised aggregate query is below.

db.product.aggregate([
    { "$match": { $and: query } },
    { "$sort": { _id: -1 } },
    {
        $project: {
            modal_name: 0,
            manufactured_by: 0,
            manufacturing_country: 0,
            stock_visible: 0,
            cash_on_delivery: 0,
            featured: 0,
            todays_deal: 0,
            publish: 0,
            created_by: 0,
            created_by_id: 0,
            unit: 0,
            variants_image: 0,
            minimum_purchase_quantity: 0,
        }
    },
    //       { $facet: { product: [{ $skip: skip }, { $limit: limit }] } },
    //       { $unwind: '$product' }
    {
        $skip: skip
    },
    {
        $limit: limit
    },
    {
        $project: {
            _id: 0,
            product: '$$ROOT'
        }
    }
])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM