Home > Back-end >  Querying nested objects using find not working in mongoose (MongoDB)
Querying nested objects using find not working in mongoose (MongoDB)

Time:09-17

I'm trying to get object with has isDraft value true but I'm also getting objects which has isDraft value false. I need only objects which has isDraft value true I'm new to Node Js. I have tried all possible way but not able to find solution for this. Can anyone help me with this ?

Below is the schema , query and response

Schema

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Contract = new Schema({
    name: {
        type: String,
        unqiue: true,
        required: true
    },
    version: [
        {
            no: {
                type: Number,
                required: true
            },
            sections: [
                {
                    sectionName: {
                        type: String,
                        required: true
                    },
                    clause: [{
                        description: {
                            type: String,
                            required: true
                        },
                    }]
                }
            ],
            approvedBy: [
                {
                    user: {
                        type: Schema.Types.ObjectId,
                        ref: 'user'
                    },
                }
            ],
            acceptedBy: [
                {
                    name: {
                        type: String,
                    },
                    eamil: {
                        type: String,
                    },
                }
            ],
            isDraft: {
                type: Boolean,
                required: true
            },
            date: {
                type: Date,
                default: Date.now
            }
        }
    ],
    createdBy: {
        type: Schema.Types.ObjectId,
        ref: 'user',
        required: true
    },

});

module.exports = mongoose.model('contract', Contract);

Query

query = {
            $and: [
                { createdBy: clientAdminDetails._id },
                { "version.isDraft": true }
            ],
        };
        await Contract
            .find(query)
            .skip(req.body.noOfItems * (req.body.pageNumber - 1))
            .limit(req.body.noOfItems)
            .exec((err, contract) => {
                if (err) {
                    return res.json(err);
                }
                Contract.countDocuments(query).exec((count_error, count) => {
                    if (err) {
                        return res.json(count_error);
                    }
                    return res.json({
                        total: count,
                        page: req.body.pageNumber,
                        pageSize: contract.length,
                        contracts: contract
                    });
                });
            });

Response

{
    "total": 1,
    "page": 1,
    "pageSize": 1,
    "contracts": [
        {
            "_id": "61449469775..",
            "name": "Octavia Blankenship",
            "version": [
                {
                    "_id": "614496593cc..",
                    "sections": [
                        {
                            "_id": "61449469775..",
                            "sectionName": "Est dolore dolorem n Updated `1323",
                            "clause": [
                                {
                                    "_id": "614494697..",
                                    "description": "Numquam nostrud et a"
                                }
                            ]
                        }
                    ],
                    "isDraft": false,
                    "no": 1,
                    "approvedBy": [],
                    "acceptedBy": [],
                    "date": "2021-09-17T13:21:29.509Z"
                },
                {
                    "_id": "614496122904ee4e046fbee8",
                    "sections": [
                        {
                            "_id": "6144955a8c0061025499606f",
                            "sectionName": "Praesentium suscipit",
                            "clause": [
                                {
                                    "_id": "6144955a8c00610254996070",
                                    "description": "Velit aperiam ut vel"
                                }
                            ]
                        }
                    ],
                    "isDraft": true,
                    "no": 2,
                    "approvedBy": [],
                    "acceptedBy": [],
                    "date": "2021-09-17T13:20:18.128Z"
                }
            ],
            "createdBy": "614367e980b29e6c...",
            "__v": 0
        }
    ]
}

CodePudding user response:

This is why using your query you are telling mongo "Give me a document where createdBy is desired id and version.isdraft is true" So, as the DOCUMENT contains both values, is returned, even existing false into the array.

To solve this you have many ways.

First one is using $elemMatch into projection (docs here). But using this way only the first element is returned, so I think you prefer other ways.

So you can use an aggregation query using $filter like this:

  • First $match by values you want (as in your query).
  • Then override version array filtering by values where isDraft = true.
db.collection.aggregate([
  {
    "$match": {
      "createdBy": "",
      "version.isDraft": true
    }
  },
  {
    "$set": {
      "version": {
        "$filter": {
          "input": "$version",
          "as": "v",
          "cond": {
            "$eq": [
              "$$v.isDraft",
              true
            ]
          }
        }
      }
    }
  }
])

Example here

  • Related