Quiero comprobar si la página del artículo solicitado es en realidad uno de los artículos del usuario que ha sido autenticado por la función passatjs req.isAuthenticated(). Estoy tratando de usar $elemMatch para lograr eso y registra al mismo usuario que está almacenado en req.user por el método de pasaporte.authenticate() pero cuando registro user._id me da indefinido. ¿Porqué es eso?
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!'); } });El uso de .exec() desencadena una consulta y devuelve una Promesa que es entonces posible, agregar una devolución de llamada en .exec() no es una forma válida de esperar a que se resuelva la promesa según la documentación de Mongoose para la que se usa
[devolución de llamada] Los parámetros opcionales de «Función» dependen de la función a la que se llama
Las operaciones asíncronas de Mongoose, como .save() y las consultas, devuelven las funciones. Esto significa que puede hacer cosas como MyModel.findOne({}).then().catch() y await MyModel.findOne({}).exec() si usa async/await.
Al llamar a .exec (), ejecuta su consulta y devuelve una promesa de que puede esperar en la función asíncrona al hacerlo algo así como
try{ const res = await MyModel.findOne({}).exec() }catch(err){ console.log(err) //err handling here }Lo que esperaría que se resuelva la promesa y le proporcione el resultado/error de manejo. Usar await sin .exec() también es un enfoque válido, se puede encontrar más información en: ¿Debería usar exec() con await?
De lo contrario, puede usar el enfoque de thenable, que ejecutaría la consulta y le proporcionaría el resultado en .then() .catch().
Ejemplo:
Band.findOne({name: "Guns N' Roses"}).then(function(doc) { // use doc }).catch(function(err){ console.log(err) });Para una mejor comprensión, recomiendo encarecidamente consultar la página de documentación de Mongoose Promises