有谁知道为什么"用户"之间存在以下一对多的关系?和"帖子" (用户可以有很多帖子)不工作?我似乎已正确设置了我的猫鼬关联,但是当创建新帖子时,不仅不分配了用户,而且用户本身也与任何帖子。我不确定我在这里做错了什么。
如果您在下面看到JSON对象,则它应该具有user
值,表示创建帖子的用户。您将在下面的帖子模型中看到应该创建用户值,但不是。
我做错了什么?
{
__v: 0
_id: "587ee8f5a99b1709b012ce8f"
createdAt: "2017-01-18T04:03:01.446Z"
message: "This is my first test post!"
updatedAt: "2017-01-18T04:03:01.446Z"
}
问题:尽管在下面的帖子模型中创建了用户字段,但为什么上面的JSON中缺少用户字段?
// Setup dependencies:
var mongoose = require('mongoose');
// Setup a schema:
var PostSchema = new mongoose.Schema (
{
message: {
type: String,
minlength: 2,
maxlength: 2000,
required: true,
trim: true,
}, // end message field
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
},
{
timestamps: true,
}
);
// Instantiate our model and export it:
module.exports = mongoose.model('Post', PostSchema)
// Setup dependencies:
var mongoose = require('mongoose');
// Setup a schema:
var UserSchema = new mongoose.Schema (
{
username: {
type: String,
minlength: 2,
maxlength: 20,
required: true,
trim: true,
unique: true, // username must be unique
dropDups: true,
lowercase: true,
validate: {
validator: function(username) {
var regex = /^[a-z0-9_]+$/i;
return regex.test(username);
},
message: 'Username may contain only letters, numbers or underscores.',
},
}, // end username field
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}],
},
{
timestamps: true,
});
// Instantiate our model and export it:
module.exports = mongoose.model('User', UserSchema)
注意:这是提交帖子表单时运行的方法。
// Grab our Mongoose Models:
var User = require('mongoose').model('User');
var Post = require('mongoose').model('Post');
module.exports = {
// Creates a new post for logged in user:
newPost: function(req, res) {
Post.create(req.body)
.then(function(newPost) {
return res.json(newPost);
})
.catch(function(err) {
return res.json(err);
})
}
};
是否有人知道我的关联是否设置不正确,这就是为什么我没有在各自的字段中显示任何实际帖子或用户?
似乎我的服务器端控制器正在正常触发,因为实际创建了帖子。但是协会本身并没有联系起来,我不确定我做错了什么。
答案 0 :(得分:0)
我在下面添加了一个简单的答案来跟进上面的例子。基本上,@ cdbajorin是正确的,我心不在焉地认为有一些自动化正在进行,并没有通过正确的mongoose命令正确地遵循以实现我想要的结果。
我的问题的解决方案如下:
posts
属性更新为空数组,而不是mongoose.Schema.Types.ObjectID
,因为无论如何都不会存储对象ID,我误解了它是如何工作的。代码:
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}],
相反,应该简单地写一下:
posts: [],
服务器控制器中的newPost
方法应修改如下(请参阅内联注释以澄清):
newPost: function(req, res) {
// creates new post:
Post.create(req.body)
.then(function(newPost) {
// look up current user based on session ID:
// note: session setup not shown in this example.
User.findById(req.session.userID)
.then(function(user) {
// push new post into users.posts array from model setup**:
user.posts.push(newPost);
user.save();
return res.json(newPost);
})
})
.catch(function(err) {
return res.json(err);
})
这确实解决了正在生成的新帖子的问题,然后将其推送到用户的posts
数组(来自UsersSchema
)。
虽然初始帖子的问题已经解决,但人们可能会质疑这是否是数据库管理的最佳用途。如此示例所示,在用户内部存储帖子会占用大量空间,因为用户和帖子开始加起来。
此帖最终会在数据库中重复两次:首先,作为posts
集合中的文档本身,其次,作为posts
数组中UserSchema
数组中的对象。
更好的解决方案是将帖子保留为posts
集合中的唯一文档,但将会话信息中的userID添加到其中。然后,如果出于任何原因需要所有用户的帖子,则基于userID对Posts集合的查询将返回具有分配给它的该用户ID的所有帖子。然后,数据库中只存在一个帖子的副本而不是两个。
**附加说明:修改现有文档的另一种方法是使用实例方法,其中实际方法将插入到用户模型(Schema)文件中,并在需要时调用:
例如,在module.exports
模型中的UserSchema
行之前插入以下代码,可以在需要时方便地访问此功能:
UserSchema.methods.addPost = function(post) {
this.posts.push(post);
this.save();
return true;
};
要从我们的服务器控制器调用此实例方法,我们可以按如下方式重新编写Controller:
User.findById(req.session.userID)
.then(function(user) {
// call our instance method above:
user.addPost(newPost);
return res.json(newPost);
});
将通过实例方法推送和保存帖子,该方法已内置到实例对象本身中。