198

I'm trying to select only a specific field with

exports.someValue = function(req, res, next) {
    //query with mongoose
    var query = dbSchemas.SomeValue.find({}).select('name');

    query.exec(function (err, someValue) {
        if (err) return next(err);
        res.send(someValue);
    });
};

But in my json response i'm receiving also the _id, my document schema only has two fiels, _id and name

[{"_id":70672,"name":"SOME VALUE 1"},{"_id":71327,"name":"SOME VALUE 2"}]

Why???

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
TlonXP
  • 3,325
  • 3
  • 26
  • 35

8 Answers8

296

The _id field is always present unless you explicitly exclude it. Do so using the - syntax:

exports.someValue = function(req, res, next) {
    //query with mongoose
    var query = dbSchemas.SomeValue.find({}).select('name -_id');

    query.exec(function (err, someValue) {
        if (err) return next(err);
        res.send(someValue);
    });
};

Or explicitly via an object:

exports.someValue = function(req, res, next) {
    //query with mongoose
    var query = dbSchemas.SomeValue.find({}).select({ "name": 1, "_id": 0});

    query.exec(function (err, someValue) {
        if (err) return next(err);
        res.send(someValue);
    });
};
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • 5
    I think `.select` just is a filter to choose field after you get all of that, my recommendation is to use `.find({}, 'name -_id')` – hong4rc Mar 02 '19 at 16:15
  • 5
    @Hongarc `.find({}, 'name -_id')` seems not working? – Shanika Ediriweera May 29 '19 at 01:53
  • is there is a way to get the value direct without an obj like [ 'value1', 'value2', 'value3' ] instead of [ 'name':'value1', 'name':'value2', 'name':'value3' ] – M.Amer Jul 14 '19 at 14:21
  • I get an error using this because apparently I can't use a mixe of inclusions and rejections. I figured I should pass as argument to the `.select()` only this id to exclude it : `.select({ "_id":0 })` – Oriun Jan 19 '21 at 15:49
82

There is a shorter way of doing this now:

exports.someValue = function(req, res, next) {
    //query with mongoose
    dbSchemas.SomeValue.find({}, 'name', function(err, someValue){
      if(err) return next(err);
      res.send(someValue);
    });
    //this eliminates the .select() and .exec() methods
};

In case you want most of the Schema fields and want to omit only a few, you can prefix the field name with a - (minus sign). For ex "-name" in the second argument will not include name field in the doc whereas the example given here will have only the name field in the returned docs.

Aakash
  • 21,375
  • 7
  • 100
  • 81
  • 37
    For those who want to filter multiple fields, don't seperate them with comma, just plain space: `blogItemModel.find({}, 'title intro_image intro_text publish_date', function(err, blog_items){..` – Starwave Oct 10 '15 at 18:37
  • 1
    for those who want to use where clause in above **dbSchema.Somevalue.find({userEmail:'test@test.com'},'userEmail -_id', function(err, someValue)** – user2180794 May 26 '16 at 07:15
  • 1
    multiple fields would be ['name', 'field2', 'field3', 'etc'] instead of just 'name' – Eray T Dec 24 '18 at 19:05
34

There's a better way to handle it using Native MongoDB code in Mongoose.

exports.getUsers = function(req, res, next) {

    var usersProjection = { 
        __v: false,
        _id: false
    };

    User.find({}, usersProjection, function (err, users) {
        if (err) return next(err);
        res.json(users);
    });    
}

http://docs.mongodb.org/manual/reference/method/db.collection.find/

Note:

var usersProjection

The list of objects listed here will not be returned / printed.

Shea Hunter Belsky
  • 2,815
  • 3
  • 22
  • 31
ElvinD
  • 667
  • 1
  • 7
  • 10
33

Tip: 0 means ignore & 1 means show.

Example 1:

User.find({}, { createdAt: 0, updatedAt: 0, isActive: 0, _id : 1 }).then(...)

Example 2:

User.findById(id).select("_id, isActive").then(...)

Example 3:

User.findById(id).select({ _id: 1, isActive: 1, name: 1, createdAt: 0 }).then(...)
Nishant Shah
  • 2,022
  • 22
  • 20
20

DB Data

[
  {
    "_id": "70001",
    "name": "peter"
  },
  {
    "_id": "70002",
    "name": "john"
  },
  {
    "_id": "70003",
    "name": "joseph"
  }
]

Query

db.collection.find({},
{
  "_id": 0,
  "name": 1
}).exec((Result)=>{
    console.log(Result);
})

Output:

[
  {
    "name": "peter"
  },
  {
    "name": "john"
  },
  {
    "name": "joseph"
  }
]

Working sample playground

link

Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54
16

Exclude

Below code will retrieve all fields other than password within each document:

const users = await UserModel.find({}, {
  password: 0 
});
console.log(users);

Output

[
  {
    "_id": "5dd3fb12b40da214026e0658",
    "email": "example@example.com"
  }
]

Include

Below code will only retrieve email field within each document:

const users = await UserModel.find({}, {
  email: 1
});
console.log(users);

Output

[
  {
    "email": "example@example.com"
  }
]
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ziishaned
  • 4,944
  • 3
  • 25
  • 32
5

The precise way to do this is it to use .project() cursor method with the new mongodb and nodejs driver.

var query = await dbSchemas.SomeValue.find({}).project({ name: 1, _id: 0 })
Ashh
  • 44,693
  • 14
  • 105
  • 132
  • 4
    `.project()` works only with aggregate. If you want to use it with find use second argument in `find({},{ name: 1, _id: 0 })` method. – Sham Sep 10 '18 at 08:55
  • No with the new mongodb node driver you have to use this way. But with mongoose you can use second argument. – Ashh Sep 10 '18 at 09:07
  • 1
    ah, it is in nodejs driver. – Sham Sep 10 '18 at 12:14
  • Don't understand why, but in new versions @Anthony is right...Lower versions you can do it this way...very messy – ackuser Sep 13 '18 at 16:10
4

I found a really good option in mongoose that uses distinct returns array all of a specific field in document.

User.find({}).distinct('email').then((err, emails) => { // do something })

Steve F.
  • 71
  • 1
  • 2