'Why does this Mongoose query return the expected result and yet I'm not able to tap into its properties?
I want to check whether the requested article page is actually one of the articles of the user who's been authenticated by passportjs req.isAuthenticated() function. I'm trying to use $elemMatch to achieve that and it logs the same user that's stored in req.user by passport.authenticate() method but when I log user._id it gives me undefined. Why is that?
const express = require('express');
const http = require('http');
const mongoose = require("mongoose");
const session = require("express-session");
const passport = require('passport');
const passportLocalMongoose = require('passport-local-mongoose');
const app = express();
const server = http.createServer(app);
mongoose.connect("mongodb://localhost:27017/userDB");
const articleSchema = new mongoose.Schema({
name: String
});
const userSchema = new mongoose.Schema({
email: String,
password: String,
articles: [articleSchema]
});
const User = new mongoose.model("User", userSchema);
const Article = new mongoose.model("Article", articleSchema);
app.get('/:articlename/:articleId', (req, res) => {
let articleName = req.params.articlename,
articleId = req.params.articleId;
if (req.isAuthenticated()) {
console.log(req.user); // prints the authenticated user
User.find({ articles: { $elemMatch: { "_id": articleId, "name":articleName } } }, function(err, user){
if(err){
console.log(err);
}else{
console.log("This article belongs to " + user); // outputs the expected user
console.log("This article belongs to user with an id " + user._id); // outputs undefined
}
}
)
} else {
console.log('Not Authenticated!');
}
});
Solution 1:[1]
Using .exec() triggers a query and returns a Promise which is thenable, adding a callback in .exec() is not a valid way to wait for the promise to be resolved as per Mongoose documentation it is used for
[callback] «Function» optional params depend on the function being called
Mongoose async operations, like .save() and queries, return thenables. This means that you can do things like MyModel.findOne({}).then().catch() and await MyModel.findOne({}).exec() if you're using async/await.
Upon calling .exec() it executes your query and returns a promise that you can await in async function by doing so something like
try{
const res = await MyModel.findOne({}).exec()
}catch(err){
console.log(err)
//err handling here
}
Which would await the promise to be resolved and provide you with the result/handle error. Using await without .exec() is also a valid approach, more information can be found at: Should You Use exec() With await?
Otherwise you can use the thenable approach, which would execute the query and provide you with the result in .then() .catch().
Example:
Band.findOne({name: "Guns N' Roses"}).then(function(doc) {
// use doc
}).catch(function(err){ console.log(err) });
For better understanding, I would highly recommend checking out Mongoose Promises documentation page
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Adam Ma |
