【问题标题】:Trouble referencing/populating a mongoose model in another model在另一个模型中引用/填充猫鼬模型时遇到问题
【发布时间】:2023-03-18 18:50:01
【问题描述】:

背景:允许用户发布投票的应用程序。
我在 User 模型中填充对 Polls 模型的引用时遇到了一些麻烦。我正在使用 mongoose.populate 来尝试填充民意调查。在我的路线中,填充功能无法正常工作(返回的用户为空)。这是我的模型...

users.js:

// models/users.js

var mongoose = require('mongoose'),
    Poll = require('./poll');

//define the schema for our user model
var userSchema = mongoose.Schema({
    local:{
        email: String,
        password: String,
        name: String
    },
    twitter:{
        id: String,
        token: String,
        name: String
    },
    polls:[{type: mongoose.Schema.Types.ObjectId, ref:'Poll'}]
});

poll.js:

//load mongoose
var mongoose = require('mongoose'),
    User = require('./user');


var pollSchema = mongoose.Schema({
       name:String,
       options:[String],
       creator: {type:mongoose.Schema.Types.ObjectId, ref:'User'}
});


module.exports = mongoose.model('Poll', pollSchema);

这是我要在...中实现人口的路线

 //require user and poll model 
 var User = require('../models/user'),
 Poll = require('../models/poll');

 app.post('/dashboard', isLoggedIn, function(req,res){ 

    var poll = {name: req.body.name, 
                options: req.body.option, 
                creator: req.user.local.id};

    //create new poll 
    var newPoll = new Poll();
    newPoll.polls = poll;

    //find the user with the request id and populate polls reference in User (UserSchema)
    User.findById(req.user.local.id)
         .populate('polls')
          .exec(function(err,user){ // cant figure this out...

              if(err){return err;}

              console.log(user); // yields null

              res.send({success:true, message: "Post Successful!"});

           });        
     });

任何帮助、建议、想法将不胜感激。谢谢。

【问题讨论】:

    标签: javascript node.js mongoose mongoose-populate mongoose-schema


    【解决方案1】:

    在您提交的代码中,您永远不会显式创建User

    有两种方法可以处理您想做的事情,一种比另一种更好,我会解释原因。

    您可以像这样向您的用户模型添加一组投票:

    var userSchema = new mongoose.Schema({
        local:{
            email: String,
            password: String,
            name: String
        },
        twitter:{
            id: String,
            token: String,
            name: String
        },
        polls:[{type: mongoose.Schema.Types.ObjectId, ref:'Poll'}]
    });
    

    请注意,您应该指定您的 userSchema = new mongoose.Schema。

    如果这是您的选择,那么当您创建新的 Poll 实例时,您必须创建 Poll,检索适当的用户 (User.findById),然后将 Poll._id 推送到 user.polls,并保存用户.
    这种方法将允许您在检索用户对象时简单地调用 .populate('polls') 以获取结果集中的所有用户投票。

    或者,您可以将 polls 数组排除在 User 模型之外,只需在您的 Poll 架构中创建引用:

    var pollSchema = new mongoose.Schema({
           name:String,
           options:[String],
           creator: {type:mongoose.Schema.Types.ObjectId, ref:'User'}
    });
    

    再次注意,您应该在 mongoose.Schema 声明中使用 new

    如果采用这种方法,则只需在创建时将 user._id 添加到 poll 对象即可。

    然后,如果您愿意,您可以在检索投票时检索用户:

    Poll.findById(...however you are retrieving your Poll id...)
             .populate('creator')
              .exec(function(err, poll){....
    

    如果您想列出给定用户发布的所有民意调查,只需执行以下操作:

    Poll.find({"creator": req.params.userId})
        .populate('creator')
        .exec(function(err, poll) {
            if(err) return err;
            res.json(poll);
        };
    

    上述代码中的 req.params.userId 不应被视为文字,并且取决于您的应用程序如何检索用户 ID,同样响应返回方式取决于您的特定应用程序,在上面的代码中它返回由用户创建的民意调查数组作为 json 对象。

    出于一个原因,第二种方法可能更好,它可以避免文档膨胀。 我似乎没有足够的声誉来评论或降级以前的答案,但在一个严重的方面它是不正确的。 您绝对不必在用户架构中拥有民意调查数组,并且在民意调查架构中拥有用户(创建者)来解决填充调用。

    任何时候,如果您有一个由没有边界的模型架构引用的数组(用户可以根据需要创建任意数量的投票),您就会冒着数据库中每个用户文档的大型系统变得庞大的风险......对于用户创建的每个投票,您将在 Polls 集合中添加一个新的投票文档,并且您正在增加父用户文档的大小。

    您实际上将相同的信息存储了两次.. 使用任何数据库都是不好的做法。

    如果您的父对象被限制为它可以拥有的子对象的数量,例如用户在编程上被限制为创建 3 个投票,那么您可以将数组添加到 User 模型中。

    但是,如果对孩子的成长没有强制限制,假设用户可以根据需要创建任意数量的投票,那么我建议您在 User 架构中不要有投票数组,而是有一个创建者在引用创建用户的轮询架构中。

    在任何一种情况下,做一个或另一个,而不是两者都做......在任何一种情况下,都有一种有效的方法来获取关系的数据,而无需将关系存储在两个不同的文档中。

    【讨论】:

      【解决方案2】:

      Mongoose 中的种群是一个很棒的功能。从我在您的代码中看到的内容来看,您似乎没有为用户分配池。您有第一部分引用用户内部的池,但没有第二部分引用池内部的用户,猫鼬需要两者都执行操作。

      我认为您希望池具有名称和选项列表。我可以在您的代码中看到一个包含一组池的池,因此我更改了池模式以适应您的解释。

      尝试使用这个新的池架构在您的池中添加对用户的引用:

      pools.js

      var mongoose = require('mongoose');
      
      var pollSchema = mongoose.Schema({
             name:String,
             options:[String],
             creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
      });
      
      
      module.exports = mongoose.model('Poll', pollSchema);
      

      现在,在保存池时,不要忘记添加您的用户参考。您正在为用户填充池,因此在 mongoose 回调中传递的对象将不是池列表,而是您要查找的用户。感谢人口,您将在属性 pools 中获得对象列表而不是 id 列表。

       var User = require('../models/user'),
       Poll = require('../models/poll');
      
       app.post('/dashboard', isLoggedIn, function(req,res){ 
      
          var poll = {
             name: req.body.name, 
             options: req.body.option, 
             creator: req.user.local.id
           };
      
          var newPoll = new Poll();
          newPoll.polls = poll;
      
          User.findById(req.user.local.id)
               .populate('polls')
                .exec(function(err, user){
                 /*
                   You should get in user object something like:
                   {
                     local: {...},
                     twitter: {...},
                     pools: [{
                       name: 'Pool1',
                       options: [...]
                     }]
                    }
                 */
                 });        
           });
      });
      

      【讨论】:

      • 感谢您的帮助! Populate 绝对是一个强大的猫鼬功能;不过,我仍在努力解决它。我更改了我的代码以遵循您发布的内容,但是 exec 回调函数中返回的用户对象为我返回了 null。我更改了原始帖子中的代码以反映我现在拥有的内容。
      • 原来用户 id 是错误的(应该是 req.user.local._id)。之后一切顺利。再次感谢您的帮助。
      猜你喜欢
      • 1970-01-01
      • 2020-02-23
      • 2020-11-02
      • 2021-05-16
      • 2021-12-25
      • 2021-06-29
      • 2021-04-24
      • 2021-05-24
      • 2021-08-17
      相关资源
      最近更新 更多