When Node has to do any I/O, like reading from a database, it will be done asynchronously. Methods like User.findOne and Query#exec will never return a result upfront so article.owner will not be properly undefined in your example.
The result of an asynchronous query will only be available inside of your callback, which is only invoked when your I/O has finished
article.owner = User.findOne({ name : 'ABC' }) .exec(function (err, user){
// User result only available inside of this function!
console.log(user) // => yields your user results
})
// User result not available out here!
console.log(article.owner) // => actually set to return of .exec (undefined)
What asynchronous code execution means in the above example: When Node.js hits article.owner = User.findOne... it will execute User.findOne().exec() and then move straight onto console.log(article.owner) before .exec has even finished.
Hope that helps clarify. It takes a while to get used to async programming it but it will make sense with more practice
Update To answer your specific problem, one possible solution would be:
User.findOne({name: 'ABC'}).exec(function (error, user){
article.owner = user._id; // Sets article.owner to user's _id
article.save() // Persists _id to DB, pass in another callback if necessary
});
Remember to use Query#populate if you want to load your user with the article like so:
Article.findOne({_id: <some_id>}).populate("owner").exec(function(error, article) {
console.log(article.owner); // Shows the user result
});