node.js - 我尝试在猫鼬中使用 Populate 但它没有用
问题描述
大家好,我有一个问题,也许你可以帮助我。所以基本上我在猫鼬中创建了两个集合,一个用于用户注册或登录时的详细信息,另一个用于他们发布的食谱。 我还想将用户发布的每个配方保存在用户集合中(如填充猫鼬的属性)。就像 user1 发布一个 recipe1 那么它应该保存在食谱集合以及发布这个的用户数据中。我尝试为此使用Populate 方法,如下面的代码所示,但是当我发布一些食谱时,它只存储在食谱集合中,并且用户集合中的“posts”键始终为空。我还想将配方保存在用户集合的“帖子”键中。请指导我如何做到这一点。
require('dotenv').config()
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const requestObj = require("request");
const https = require("https");
const multer = require("multer");
const path = require("path");
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const findOrCreate = require('mongoose-findorcreate');
const app = express();
const GoogleStrategy = require('passport-google-oauth20').Strategy;
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static("public"));
app.use(session({
secret: "This is my secret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// Mongoose connection
mongoose.connect("mongodb://localhost:27017/recipeUsers", {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.set('useCreateIndex', true);
//mongoose schema
const userSchema = new mongoose.Schema({
username: String,
password: String,
googleId: String,
name: String,
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Recipe'
}]
});
const recipeSchema = new mongoose.Schema({
genre: String,
name: String,
description: String,
ingredients: [{
type: String
}],
method: [{
type: String
}],
imageName: String,
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
// model
const Recipe = mongoose.model("Recipe", recipeSchema);
const User = mongoose.model("User", userSchema);
module.exports = {
User,
Recipe,
}
passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:5000/auth/google/index",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
// console.log(profile);
User.findOrCreate({
googleId: profile.id,
name: profile.displayName
}, function(err, user) {
return cb(err, user);
});
}
));
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/img/uploads")
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
var upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024
}
});
app.use((req, res, next) => {
res.locals.isAuthenticated = req.isAuthenticated();
if (req.isAuthenticated()) {
currentUser = req.user.name;
}
next();
});
app.get("/", function(req, res) {
res.render("index");
});
app.get("/index", (req, res) => {
res.render('index');
});
app.get("/about", function(req, res) {
res.render("about");
});
app.route("/search")
.get(function(req, res) {
res.render("search");
})
.post(function(req, res) {
const searchRecipe = req.body.recipeName;
Recipe.findOne({
name: searchRecipe
}, (err, foundRecipe) => {
if (err) {
res.send(err);
} else {
if (foundRecipe) {
res.render("recipe", {
dishName: foundRecipe.name,
descrip: foundRecipe.description,
genre: foundRecipe.genre,
ingredients: foundRecipe.ingredients,
steps: foundRecipe.method,
author: foundRecipe.author,
dishImage: foundRecipe.imageName
});
} else {
res.redirect("/Failure");
}
}
});
});
app.get("/Failure", function(req, res) {
res.render("Failure");
});
app.route("/post")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("post", {
message: ""
});
} else {
res.redirect("/login");
}
})
.post(upload.single('dishImage'), function(req, res, next) {
const dishType = req.body.recipeGenre;
const description = req.body.description;
const dishName = req.body.dishName;
const ingredient = req.body.ingredients;
const step = req.body.steps;
// const authorName = req.body.author;
// const url = "https://polar-oasis-10822.herokuapp.com/recipes";
const file = req.file;
if (!file) {
const error = new Error("Please upload a image");
error.httpStatusCode = 400;
return next(error);
}
// console.log(req.user);
const dish = new Recipe({
genre: dishType,
name: dishName,
description: description,
ingredients: ingredient,
method: step,
imageName: file.filename,
});
dish.save((err) => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
})
.populate('posts').exec((err, posts) => {
console.log("Populated User " + posts);
})
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
app.get("/menu", function(req, res) {
res.render("menu");
});
app.get('/auth/google',
passport.authenticate('google', {
scope: ["profile"]
})
);
app.get('/auth/google/index', passport.authenticate('google', {
failureRedirect: '/login'
}), function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
});
app.get("/logout", (req, res) => {
req.logout();
res.redirect('/');
});
app.route("/signup")
.get((req, res) => {
res.render("signup");
})
.post((req, res) => {
User.register({
username: req.body.username,
name: req.body.name,
}, req.body.password, (err, user) => {
if (err) {
console.log(err);
res.redirect("/signup");
} else {
passport.authenticate("local")(req, res, () => {
res.redirect('/');
});
}
});
})
app.route("/login")
.get((req, res) => {
res.render("login");
})
.post((req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, () => {
res.redirect("/");
});
}
});
})
app.listen(process.env.PORT || 5000, function() {
console.log("server is running on port 5000");
});
解决方案
我相信你的问题在这里:
dish.save((err) => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
})
.populate('posts').exec((err, posts) => {
console.log("Populated User " + posts);
})
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
您正在使用populate
作为更改数据集元素的函数,但这只是打印来自不同集合的结果的技巧,在根中,它们是不同的;如果您希望它们在同一个文档中,则必须使用子文档。populate
不更改文档路径。
假设我没有输入任何错误,您必须更正自己或让我知道,这应该可以解决您的问题;只需使用填充将我们的文档打印为一个,而不是保存。
app
.route("/post")
.get(function(req, res) {
if (req.isAuthenticated()) {
res.render("post", {
message: ""
});
} else {
res.redirect("/login");
}
})
.post(upload.single("dishImage"), function(req, res, next) {
const dishType = req.body.recipeGenre;
const description = req.body.description;
const dishName = req.body.dishName;
const ingredient = req.body.ingredients;
const step = req.body.steps;
const username = req.body.author; //make sure this information is passed to req.body
// const url = "https://polar-oasis-10822.herokuapp.com/recipes";
const file = req.file;
if (!file) {
const error = new Error("Please upload a image");
error.httpStatusCode = 400;
return next(error);
}
// console.log(req.user);
const dish = new Recipe({
genre: dishType,
name: dishName,
description: description,
ingredients: ingredient,
method: step,
imageName: file.filename
});
dish.save(err => {
if (err) {
res.send(err);
} else {
User.findOne({
_id: req.user._id
}).then(user => {//I have changed just here! I have eliminated the populate call
user.posts.push(dish._id);
user.save().then(() => {
console.log("okay");
});
});
res.render("post", {
message: "Your Recipe is successfully posted."
});
}
});
});
由于您的代码很大,我可能遗漏了一些东西,如果我误解了您想要的内容,请告诉我。
参考
推荐阅读
- jenkins - 詹金斯流水线成一个时间表
- dji-sdk - 在 iOS 中将 DJI 视频直播到 youtube
- javascript - 反应本机中具有变量的图像源
- css - CSS Transform Translate 在 Chrome 和 Firefox 中的定位不同?
- tsql - 分组后的SQL重新编号索引
- google-maps - 如何从应用程序本身启用位置跟踪权限?
- java - @SessionTarget,休眠会话为空
- python - 500内部服务器错误!!- 从 python2.7 迁移到 python3.6 的 django 应用程序中的 wsgi 问题
- python - Read telegram group message
- javascript - Rails - 添加 .js.erb 文件时未加载 Ajax 请求