如何在 NodeJS 和 Mongoose 中填充需要引用用户名的帖子
Posted
技术标签:
【中文标题】如何在 NodeJS 和 Mongoose 中填充需要引用用户名的帖子【英文标题】:How to populate in NodeJS and Mongoose a Post which need to be referred to a Username 【发布时间】:2020-05-08 13:56:30 【问题描述】:我在我的 NodeJs API 和 Mongo 中遇到问题,我必须使用用户名字符串在字段用户名中发布和填充。
当我发布时,我收到此错误:
“TypeError: newPost.save(...).populate 不是函数”
后模型:
const mongoose = require("mongoose");
const schema =
text:
type: String,
required: true,
unique: true
,
username:
type: mongoose.Schema.Types.String,
ref: "Profile",
required: true
,
image:
type: String,
default: "https://via.placeholder.com/150",
required: false
,
createdAt:
type: Date,
default: Date.now,
required: false
,
updatedAt:
type: Date,
default: Date.now,
required: false
;
const collectionName = "posts";
const postSchema = mongoose.Schema(schema);
const Post = mongoose.model(collectionName, postSchema);
module.exports = Post;
这是我在做 post 方法的地方:
postRouter.post("/", async (req, res) =>
try
const newPost = await Posts.create(req.body);
const username = await Profiles.findOne(
username: req.body.username
);
if (!username) res.status(400).send("Username not found");
newPost.save().populate(username.username);
res.send( success: "Post added", newPost );
catch (error)
res.status(500).send(error);
console.log(error);
);
响应输出应该如何:
"_id": "5d93ac84b86e220017e76ae1", //server generated
"text": "this is a text 12312 1 3 1", <<--- THIS IS THE ONLY ONE SENDING"
"username": "admin",<-- FROM REQ.body or params ???
"createdAt": "2019-10-01T19:44:04.496Z", //server generated
"updatedAt": "2019-10-01T19:44:04.496Z", //server generated
"image": ... //server generated on upload, set a default here
我也很高兴知道这样的路线的想法是否有意义,因为帖子需要有用户名,如果最好将它放在正文或请求的参数中。
【问题讨论】:
检查这个mongoosejs.com/docs/populate.html你会更好地了解填充 这将是您的问题及其解决方案。 HELP 【参考方案1】:当我发布时,我收到此错误:“TypeError: newPost.save(...).populate is not a function”
您只需在save
返回类型上使用populate
,即(来自API documentation)Promise
。需要在populate
调用之前等待承诺。
postRouter.post("/", async (req, res) =>
try
const newPost = await Posts.create(req.body);
const username = await Profiles.findOne(
username: req.body.username
);
if (!username) res.status(400).send("Username not found");
const addedPost = await newPost.save(); // <-- Here
addedPost.populate(username.username); // <-- Then populate here
res.send( success: "Post added", newPost );
catch (error)
res.status(500).send(error);
console.log(error);
);
我也很高兴知道这样的路线的想法是否有意义,因为帖子需要有用户名,如果最好将它放在正文或请求的参数中。
您的路线似乎是 /
以创建新帖子。将其命名为/post
可能更清楚。
如果您将用户名放入请求中,例如:/post/:username
,则表明帖子需要用户名。但是您无法提供所需的其他信息。因此,如果您的应用程序增长并且您需要另一个需要参数,您必须对 API 路由进行重大更改。
【讨论】:
【参考方案2】:您无需填充配置文件用户名,因为您已经在 req.body.username
中拥有该值。
您的代码也存在一些问题:
1-) 您已经使用Posts.create
创建了一个帖子,因此无需使用newPost.save()
2-) 如果不需要删除newPost.save()
,则需要添加等待。
3-) 如果不需要删除newPost.save()
,则保存后不能使用填充。
4-) 您需要在 400 情况下返回响应,使用您的代码,代码将在 400 情况下执行。
5-) 在 catch 块中,你永远看不到 console.log(error)
6-) 您正在创建一个帖子,并且在您检查用户名是否存在于个人资料中之后。 先检查用户名是否存在是正确的,找到后才创建帖子。
所以代码一定是这样的:
postRouter.post("/", async (req, res) =>
try
const username = req.body;
const profile = await Profiles.findOne( username );
if (!profile)
return res.status(400).send("Username not found");
let newPost = await Posts.create(req.body);
newPost.username = username;
res.send( success: "Post added", newPost );
catch (error)
console.log(error);
res.status(500).send(error);
);
【讨论】:
【参考方案3】:试试下面的代码 考虑到 req.body.username 将是猫鼬对象 Id
postRouter.post("/", async (req, res) =>
try
const username = await Posts.findOne(
username: req.body.username
);
if (!username)
res.status(400).send("Username not found");
else
const newPost = await Posts.create(req.body); //might need remove if double entry created
const post = await Posts.populate(newPost,
path: 'username'
)
res.send(
success: "Post added",
newPost
);
catch (error)
res.status(500).send(error);
console.log(error);
);
【讨论】:
以上是关于如何在 NodeJS 和 Mongoose 中填充需要引用用户名的帖子的主要内容,如果未能解决你的问题,请参考以下文章
Mongoose/Nodejs - 填充函数仅返回用户的对象 ID
无法读取未定义的属性“名称” - mongoose、express、nodeJS、ejs