在Express应用程序中关联两个mongoose数据库

问题描述 投票:0回答:1

我有两个猫鼬DB模式,一个User和一个Profile

var userSchema = new mongoose.Schema({
    username: String,
    password: String,
    type:     String
});

userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", userSchema);

var profileSchema = new mongoose.Schema({
    username: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    email: { 
        type: String,
        default: ""
    },
    skill: { 
        type: String,
        default: ""
    }
});

module.exports = mongoose.model("Profile", profileSchema);

我首先使用passport-js注册和验证用户,如果这是成功的,那么我想创建使用Profileusername填充type数据库。然后我将允许用户更新这个Profile db(但不是Users)。在docs之后我试图使用.populate,在Profile创建一个与User相同信息的条目:

router.post("/signup", function(req, res) {
    var newUser = new User({username: req.body.username, type: req.body.type});

    User.register(newUser, req.body.password, function(err, user){
        if(err){
            console.log(err.message);
            return res.render("signup");
        }
        passport.authenticate("local")(req, res, function(){
            Profile.findById(newUser._id).populate("username").exec(function(err, foundUser){
                if(err){
                    console.log("Problem populating the profiles DB");
                }
                else{
                    console.log("New user:" + newUser._id);
                    res.redirect("profile/" + newUser._id);
                }
            });
        });
    });
});

这传递没有错误,但我的Profiles数据库是空的。

谁能看到我在这里做错了什么?

我也试过(在同一条路线内):

Profile.create(newUser, function(err, newlyCreated){
    if(err){
        console.log(err);
    } else {
        console.log("Added user to profile db:" + newUser._id);
        console.log("New user:" + newUser._id);
        res.redirect("profile/" + newUser._id);
     }
 });

但这失败了,错误:

{ DocumentNotFoundError: No document found for query "{ _id: 5c6d9512a4a301b73b565681 }"

我正在尝试的另一种方法是:

Profile.create({username:req.body.username, type: req.body.type}, function(err, pro){
  if(err){
      console.log("Profile error: " + err);
  } else {
      console.log("Added user to profile db:" + newUser._id);
      console.log("New user:" + newUser._id);
      res.redirect("profile/" + newUser._id);
  }
});

哪个通过,但在Profiles中生成一个条目,其中_idUsers中的相应条目不同。

有人能指出我正确的方向吗?

node.js express mongoose mongoose-populate
1个回答
1
投票

您的代码的几个部分是有问题的。

你调用了newUser._id但是newUser是mongoose模型用户的实例。 _id字段是由MongoDB在将文档存储到数据库时创建的,因此在实例化对象时,字段不会被填充。将其保存到数据库时会创建它。所以你可以在_id上访问正确的user._iduser来自回调。

router.post("/signup", function(req, res) {
    var newUser = new User({username: req.body.username, type: req.body.type});

    User.register(newUser, req.body.password, function(err, user){
        if(err){
            console.log(err.message);
            return res.render("signup");
        }
        passport.authenticate("local")(req, res, function(){
            Profile.findById(user._id).populate("username").exec(function(err, foundUser){
                if(err){
                    console.log("Problem populating the profiles DB");
                }
                else{
                    console.log("New user:" + user._id);
                    res.redirect("profile/" + user._id);
                }
            });
        });
    });
});

此外,您的代码中有奇怪的部分:

  • 创建用户时,不要在profiles集合中创建新的配置文件。那么你怎么认为它可以找到一个没有创建的文档。
  • 你在Profile上调用.findById并从用户文档中传递_id,而它不是这个db的_id,所以在这个集合中没有查询_id的文档。
  • 您应该查询Profile.findOne({username: user.name})然后尝试填充您的字段:Profile.findOne({username: user.name}).populate('user')profile.user = user._id存储配置文件时。
  • 此外,如果您可以使用用户名冲突,那么您应该使用user._id查找相关文档,因此请为您的个人资料存储一个唯一值以便轻松找到它。

所以你的架构应该看起来有点不同:

var profileSchema = new mongoose.Schema({
    user: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    email: { 
        type: String,
        default: ""
    },
    skill: { 
        type: String,
        default: ""
    }
});

并且当通过此调用填充Profile.findOne({user: user._id}).populate('user')时,您将获得:

{
    user: {
        username,
        password,
        type
    },
    email,
    skill
}

记得:

  • 您不能将字符串分配给mongoose.Schema.Types.ObjectId,
  • 不要忘记在创建用户时创建配置文件,并在user._id属性中引用profile.user
  • Collection.findById(id)将使用document._id === id在集合中查找文档
  • 如果要填充未键入objectId的字段,则必须定义虚拟。 Mongoose doc很好地解释了这个:https://mongoosejs.com/docs/populate.html#populate-virtuals
  • 如果您不想在填充时发送密码,则可以限制字段:Profile.findOne({user user._id}).populate({path: 'user', select: "-password"})。此请求将删除密码字段以减少数据泄漏风险。
© www.soinside.com 2019 - 2024. All rights reserved.