首页 > 解决方案 > 如何在 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 组件上。

标签: node.jsmongodbmongoose

解决方案


由于您没有任何来自用户的参考来发布,您可以为此使用虚拟人口

首先像这样更新用户模式:(注意我添加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");
  }
});

这将给出相同的结果。


推荐阅读