在另一个模型中引用/填充猫鼬模型时出现问题

Trouble referencing/populating a mongoose model in another model

本文关键字:模型 问题 填充 另一个 引用      更新时间:2023-09-26

背景:允许用户发布投票调查的应用程序
我在User模型中填充对Polls模型的引用时遇到了一点问题。我正在使用mongooose.populate来尝试填充民意调查。在我的路由中,populate函数工作不正常(返回的用户为null)。这是我的模型

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!"});
           });        
     });

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

Mongoose中的种群是一个非常好的特性。从我在代码中看到的情况来看,您似乎没有将池分配给用户。第一部分引用用户内部的池,而第二部分引用池内部的用户,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回调中传递的对象将不是池列表,而是您要查找的用户。由于population,您将在属性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: [...]
               }]
              }
           */
           });        
     });
});

在您提交的代码中,您从未显式创建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=猫鼬。架构。

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

或者,您可以将轮询数组排除在用户模型之外,只需在您的轮询模式中创建引用:

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

再次注意,您应该在猫鼬中使用new。架构声明。

如果采用这种方法,只需添加用户即可_创建轮询对象时该对象的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对象的轮询数组。

第二种方法可能更好,原因之一是它避免了文档膨胀。我似乎没有足够的声誉来评论或降级之前的答案,但在一个严重的方面,这是不正确的您绝对不必在用户模式中有轮询数组,也不必在轮询模式中有mongose的用户(创建者)来解决填充调用

任何时候,只要你有一个由无边界的模型模式引用的数组(用户可以创建他们想要的任意多个轮询),你就会面临数据库中每个用户文档的大系统变得巨大的风险。。。对于用户创建的每个轮询,您将在"轮询"集合中添加一个新的"轮询"文档,并增加父"用户"文档的大小。

您实际上是在两次存储相同的信息。。任何数据库的不良做法。

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

然而,如果对孩子的成长没有强制限制,比如说用户可以创建他们想要的任意数量的民意调查,那么我建议你在用户模式中不要有一组民意调查,而是在民意调查模式中有一个引用创建用户的创建者。

无论哪种情况,都要做其中一种,而不是两者都做。。。无论哪种情况,都有一种有效的方法可以获得关系的数据,而无需将关系存储在两个不同的文档中。