如何在 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

使用 graphql 和 nodejs 填充猫鼬模式

无法读取未定义的属性“名称” - mongoose、express、nodeJS、ejs

NodeJS 和 Mongoose:将元素添加到现有的空数组

在 Node JS 中填充 Mongoose

尝试加入两个文档时无法在 Mongoose 中填充路径