84

I have a NodeJS application with Mongoose ODM(Mongoose 3.3.1). I want to retrieve all fields except 1 from my collection.For Example: I have a collection Product Which have 6 fields,I want to select all except a field "Image" . I used "exclude" method, but got error.. This was my code.

    var Query = models.Product.find();
    Query.exclude('title Image');

    if (req.params.id) {
        Query.where('_id', req.params.id);
    }


    Query.exec(function (err, product) {
        if (!err) {
            return res.send({ 'statusCode': 200, 'statusText': 'OK', 'data': product });
        } else {
            return res.send(500);
        }
    });

But this returns error

Express
500 TypeError: Object #<Query> has no method 'exclude'.........

Also I tried, var Query = models.Product.find().exclude('title','Image'); and var Query = models.Product.find({}).exclude('title','Image'); But getting the same error. How to exclude one/(two) particular fields from a collection in Mongoose.

Cœur
  • 37,241
  • 25
  • 195
  • 267
dany
  • 1,801
  • 7
  • 27
  • 40

10 Answers10

170

Use query.select for field selection in the current (3.x) Mongoose builds.

Prefix a field name you want to exclude with a -; so in your case:

Query.select('-Image');

Quick aside: in JavaScript, variables starting with a capital letter should be reserved for constructor functions. So consider renaming Query as query in your code.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
49

I don't know where you read about that .exclude function, because I can't find it in any documentation.

But you can exclude fields by using the second parameter of the find method.

Here is an example from the official documentation:

db.inventory.find( { type: 'food' }, { type:0 } )

This operation returns all documents where the value of the type field is food, but does not include the type field in the output.

Philipp
  • 67,764
  • 9
  • 118
  • 153
  • 1
    I read about **exclude** in [http://mongoosejs.com/docs/2.7.x/docs/query.html]. As in the answer above my **Image** field can have different values for different product(each row) – dany Jan 28 '13 at 10:10
  • 5
    He's asking about mongoose, you're using the native driver. – UpTheCreek Mar 03 '15 at 09:50
  • saved my life.. delete user.password wasn't consistently working.. was afraid to go live that way – Laurent Schwitter Aug 02 '19 at 23:48
37
Model.findOne({ _id: Your Id}, { password: 0, name: 0 }, function(err, user){
  // put your code
});

this code worked in my project. Thanks!! have a nice day.

Danieldms
  • 1,006
  • 9
  • 11
21

You could do this

const products = await Product.find().select(['-image'])
Aditya
  • 757
  • 1
  • 12
  • 23
1

I am use this with async await

async (req, res) => {
      try { 
        await User.findById(req.user,'name email',(err, user) => {
          if(err || !user){
            return res.status(404)
          } else {
            return res.status(200).json({
              user,
            });
          }
        });
      } catch (error) {
        console.log(error);
      }
1

you can exclude the field from the schema definition by adding the attribute

    excludedField : {
...
    select: false,
...
    }

whenever you want to add it to your result, add this to your find()

find().select('+excludedFiled')
Hicham Mounadi
  • 429
  • 6
  • 8
0

In the updated version of Mongoose you can use it in this way as below to get selected fields.

user.findById({_id: req.body.id}, 'username phno address').then(response => {
  res.status(200).json({
    result: true,
    details: response
  });
}).catch(err => {
  res.status(500).json({ result: false });
});
Marcel Kohls
  • 1,650
  • 16
  • 24
SaiSurya
  • 1,046
  • 8
  • 14
0

I'm working on a feature. I store a userId array name "collectedUser" than who is collected the project. And I just want to return a field "isCollected" instead of "collectedUsers". So select is not what I want. But I got this solution.

This is after I get projects from database, I add "isCollected".

for (const item of projects) {
    item.set("isCollected", item.collectedUsers.includes(userId), {
        strict: false,
    })
}

And this is in Decorator @Schema

@Schema({
timestamps: true,
toObject: {
    virtuals: true,
    versionKey: false,
    transform: (doc, ret, options): Partial<Project> => {
        return {
            ...ret,
            projectManagers: undefined,
            projectMembers: undefined,
            collectedUsers: undefined
        }
    }
}
})

Finally in my controller

projects = projects.map(i => i.toObject())

It's a strange tricks that set undefined, but it really work.

Btw I'm using nestjs.

pppppu
  • 33
  • 3
0

You can do it like this

const products = await Product.find().select({
  "image": 0
});
Anirban Das
  • 1,035
  • 1
  • 18
  • 22
0

For anyone looking for a way to always omit a field - more like a global option rather than doing so in the query e.g. a password field, using a getter that returns undefined also works

{
    password: {
      type: String,
      required: true,
      get: () => undefined,
    },
}

NB: Getters must be enabled with option { toObject: { getters:true } }

TheMonarch
  • 397
  • 4
  • 11