node.js - 如何在 Express/Mongo 中获取特定用户的所有帖子列表?
问题描述
我有一个用户和帖子模型,并且有一个用户提要,其中将显示用户提交的所有帖子。
用户.js
const mongoose = require("mongoose")
const bcrypt = require("bcrypt")
const Schema = mongoose.Schema
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
}, { timestamps: true })
userSchema.pre("save", function (next) {
if (this.password) {
const salt = bcrypt.genSaltSync(10)
this.password = bcrypt.hashSync(this.password, salt)
}
next()
})
userSchema.methods.confirmPassword = function (password) {
return bcrypt.compareSync(password, this.password)
}
const User = mongoose.model("User", userSchema)
module.exports = User
Post.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var URLSlug = require("mongoose-slug-generator");
mongoose.plugin(URLSlug);
const postSchema = new Schema({
postTitle: { type: String, required: true },
postDescription: { type: String, required: true },
userId: { type: Schema.Types.ObjectId, ref: "User" },
slug: { type: String, slug: "title" }
}, { timestamps: true }
)
postSchema.pre("save", function (next) {
this.slug = this.postTitle.split(" ").join("-");
next();
});
const Post = mongoose.model("post", postSchema);
module.exports = post;
路线如下所示:
帖子.js
router.post("/new", auth.verifyToken, postsController.newposts)
router.get("/list", postsController.listpostss)
router.get("/:id", postsController.findposts)
router.put("/:id/edit", postsController.updateposts)
router.delete("/:id/delete", postsController.deleteposts)
用户.js
router.post("/register", usersController.registerUser)
router.post("/login", usersController.loginUser)
router.get("/me", auth.verifyToken, usersController.identifyUser)
router.get("/list", usersController.listUsers)
router.get("/:id", usersController.getUser)
router.put("/:id/edit", usersController.updateUser)
router.delete("/:id/delete", usersController.deleteUser)
所以,我只希望用户提交的帖子显示在我的反应应用程序的 Feed 组件上。
解决方案
由于您没有任何来自用户的参考来发布,您可以为此使用虚拟人口:
首先像这样更新用户模式:(注意我添加toJSON: { virtuals: true }
并定义了userSchema.virtual
)
const userSchema = new Schema(
{
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true }
},
{ timestamps: true, toJSON: { virtuals: true } }
);
userSchema.virtual("posts", {
ref: "Post",
foreignField: "userId",
localField: "_id"
});
现在您可以像普通人口一样填充来自用户的帖子:
router.get("/user-posts", async (req, res) => {
try {
const userId = req.user.id; //change this to logged -in user id
const result = await User.findById(userId).populate("posts");
res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong, check logs");
}
});
假设我们有这个现有用户:
{
"_id": "5e3a885ec511414a3c37a78c",
"username": "metalHeadDev",
"email": "metal@head.dev",
"password": "123123",
"createdAt": "2020-02-05T09:18:22.948Z",
"updatedAt": "2020-02-05T09:18:22.948Z",
"__v": 0,
"id": "5e3a885ec511414a3c37a78c"
}
来自该用户的这 2 个帖子:
{
"_id": "5e3a88e2c511414a3c37a78d",
"postTitle": "title1",
"postDescription": "description1",
"userId": "5e3a885ec511414a3c37a78c",
"slug": "title1",
"createdAt": "2020-02-05T09:20:34.529Z",
"updatedAt": "2020-02-05T09:20:34.529Z",
"__v": 0
}
{
"_id": "5e3a88f1c511414a3c37a78e",
"postTitle": "title2",
"postDescription": "description2",
"userId": "5e3a885ec511414a3c37a78c",
"slug": "title2",
"createdAt": "2020-02-05T09:20:49.754Z",
"updatedAt": "2020-02-05T09:20:49.754Z",
"__v": 0
}
结果将是这样的:
{
"_id": "5e3a885ec511414a3c37a78c",
"username": "metalHeadDev",
"email": "metal@head.dev",
"password": "123123",
"createdAt": "2020-02-05T09:18:22.948Z",
"updatedAt": "2020-02-05T09:18:22.948Z",
"__v": 0,
"posts": [
{
"_id": "5e3a88e2c511414a3c37a78d",
"postTitle": "title1",
"postDescription": "description1",
"userId": "5e3a885ec511414a3c37a78c",
"slug": "title1",
"createdAt": "2020-02-05T09:20:34.529Z",
"updatedAt": "2020-02-05T09:20:34.529Z",
"__v": 0
},
{
"_id": "5e3a88f1c511414a3c37a78e",
"postTitle": "title2",
"postDescription": "description2",
"userId": "5e3a885ec511414a3c37a78c",
"slug": "title2",
"createdAt": "2020-02-05T09:20:49.754Z",
"updatedAt": "2020-02-05T09:20:49.754Z",
"__v": 0
}
],
"id": "5e3a885ec511414a3c37a78c"
}
作为替代方案,我们可以使用 mongodb 聚合框架。此解决方案不需要对架构进行任何更改,并且可以首选。
const ObjectId = require("mongoose").Types.ObjectId;
router.get("/user-posts", async (req, res) => {
try {
const userId = req.user.id; //change this to logged -in user id
const result = await User.aggregate([
{
$match: {
_id: ObjectId(userId)
}
},
{
$lookup: {
from: "posts", //must be collection name for posts
localField: "_id",
foreignField: "userId",
as: "posts"
}
}
]);
if (result.length > 0) {
res.send(result[0]);
} else {
res.status(404).send("User not found");
}
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong, check logs");
}
});
这将给出相同的结果。
推荐阅读
- reactjs - Uncaught Invariant Violation:对象作为 React 子对象无效(发现:带有键 {$$typeof,render} 的对象)
- ios - 尝试初始化图像
- python - 由于未完成的子进程而无法读取文件:Python
- ios - 将价值传递给私有财产
- javascript - 如何让列表页面记住一些参数?
- oozie - 在 Oozie 中,就像 Actions 有重试选项一样,Workflow 级别是否有类似的选项?
- node.js - 检查电子邮件 ID 是否存在而不在 NodeJS 中发送电子邮件
- google-cloud-functions - 每个项目可以部署多少次功能?
- amazon-web-services - 当 lex 不自动处理意图时如何调用 lambda?
- asp.net-mvc - AuthenticationTicket 类的标识属性