node.js - 在 express 应用中关联两个 mongoose 数据库
问题描述
我有两个猫鼬数据库模式, aUser
和 a 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注册和验证用户,如果成功,然后我想创建用and填充Profile
数据库。然后我将允许用户更新这个数据库(但不是)。按照我正在尝试使用的文档,使用与以下相同的信息创建一个条目:username
type
Profile
Users
.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);
}
});
它通过了,但产生了一个与 inProfiles
中_id
的相应条目不同的条目Users
。
有人能指出我正确的方向吗?
解决方案
您的代码有几个部分有问题。
但是,您调用newUser._id
的 newUser 是猫鼬模型 User 的实例化。该_id
字段是由MongoDB在将文档存储到数据库时创建的,因此在实例化对象时不填充该字段是合乎逻辑的。它是在将其保存到数据库时创建的。因此,您可以通过回调访问正确_id
的 on 。user._id
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(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
集合中创建新的配置文件。那么您认为它如何找到未创建的文档。 - 您正在调用
.findById
Profile 并将其_id
从用户文档传递给它,而它不是_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,
- 创建用户时不要忘记创建 Profile,并引用
user._id
内部profile.user
属性。 Collection.findById(id)
将在集合中查找文档document._id === id
- 如果要填充未键入为 objectId 的字段,则必须定义virtual。猫鼬文档很好地解释了这一点:https ://mongoosejs.com/docs/populate.html#populate-virtuals
- 如果您不想在填充时发送密码,您可以限制字段:
Profile.findOne({user user._id}).populate({path: 'user', select: "-password"})
. 此请求将删除密码字段以降低数据泄露风险。
推荐阅读
- typescript - 如何将 ImmutableJS 映射与 TypeScript 一起使用
- android - ViewModel、LiveData 和 Transformations.map
- azure - 如何为 Azure 存储过程提供分区键
- ruby-on-rails - 是否可以在 Heroku 上进行相互 ssl 身份验证?
- c++ - 在另一个类中调用一个类函数(无效使用非静态成员函数)
- angular - 带有授权标头的 Angular/Ionic CORS 错误
- android - android从图像列表视图中的url读取位图
- chai - chai 断言库是否在通过/失败的步骤中返回真/假?
- python - paypal下载账户活动记录
- python - scipy 空间获取与 3D 点和 3D 点数组的距离