68

I have the below schema (apologies that it is in coffeescript)

Schema = mongoose.Schema

AuthS = new Schema
    auth:   {type: String, unique: true}
    nick:   String
    time:   Date
Auth = mongoose.model 'Auth', AuthS

I simply want to recover one record which is definitely in my database:

Auth.findOne({nick: 'noname'}, function(obj) { console.log(obj); });

Unfortunately this always logs null. db.auths.findOne({nick: 'noname'}) in mongo shell always returns a value. What is going on?

Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
Callum Rogers
  • 15,630
  • 17
  • 67
  • 90

5 Answers5

109

Found the problem, need to use function(err,obj) instead:

Auth.findOne({nick: 'noname'}, function(err,obj) { console.log(obj); });
Callum Rogers
  • 15,630
  • 17
  • 67
  • 90
  • 3
    When I use `findOne` like this I get my data successfully but `obj` is not a `Document` object. When I try `obj.nick` and `obj[nick]` I get undefined. When I try `obj.get('nick')` I get object does not have method get. I tried many JSON conversions and creating a `doc = new Document(obj)`. I also tried `doc.toObject(obj)` and `doc.set(obj)`; – Jonathan Czitkovics Aug 26 '13 at 12:04
  • 2
    @JonathanCzitkovics I think that if you do obj.toObject() that would give you what you were looking for. – Guy Jan 05 '14 at 07:03
  • 5
    When the operation executes succesfully (err is null), but there is no match, the document will be null too. – László Kardinál Feb 23 '16 at 13:18
  • But how are you getting the object inside of findOne? I am assuming this info would be in a route. req.body? – Winnemucca Apr 23 '17 at 07:27
  • @JonathanCzitkovics . Thank you. But please let me know the reason. Only for one project i am using like this for others i can just use . symbol – user1187 Nov 20 '17 at 11:51
15

Mongoose basically wraps mongodb's api to give you a pseudo relational db api so queries are not going to be exactly like mongodb queries. Mongoose findOne query returns a query object, not a document. You can either use a callback as the solution suggests or as of v4+ findOne returns a thenable so you can use .then or await/async to retrieve the document.

// thenables
Auth.findOne({nick: 'noname'}).then(err, result) {console.log(result)};
Auth.findOne({nick: 'noname'}).then(function (doc) {console.log(doc)});

// To use a full fledge promise you will need to use .exec()
var auth = Auth.findOne({nick: 'noname'}).exec();
auth.then(function (doc) {console.log(doc)});

// async/await
async function async auth() {
  const doc = await Auth.findOne({nick: 'noname'}).exec();
  return doc;
}
auth();

See the docs if you would like to use a third party promise library.

shekhardtu
  • 4,335
  • 7
  • 27
  • 34
Isaac Pak
  • 4,467
  • 3
  • 42
  • 48
10

In my case same error is there , I am using Asyanc / Await functions , for this needs to add AWAIT for findOne

Ex:const foundUser = User.findOne ({ "email" : req.body.email });

above , foundUser always contains Object value in both cases either user found or not because it's returning values before finishing findOne .

const foundUser = await User.findOne ({ "email" : req.body.email });

above , foundUser returns null if user is not there in collection with provided condition . If user found returns user document.

Bhagvat Lande
  • 1,392
  • 3
  • 17
  • 34
2

You might want to consider using console.log with the built-in "arguments" object:

console.log(arguments); // would have shown you [0] null, [1] yourResult

This will always output all of your arguments, no matter how many arguments you have.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
Neil Gaetano Lindberg
  • 2,488
  • 26
  • 23
0

Use obj[0].nick and you will get desired result,

NaturalCoder
  • 128
  • 9