【问题标题】:Why are my Mongoose One-To-Many Relationships not associating properly?为什么我的 Mongoose 一对多关系没有正确关联?
【发布时间】:2017-06-02 08:50:30
【问题描述】:

有谁知道为什么“用户”和“帖子”(用户可以有很多帖子)之间的以下一对多关系不起作用?看来我已经正确设置了我的猫鼬关联,但是当创建新帖子时,不仅没有分配了用户,而且用户本身也没有与 any 关联> 帖子。我不确定我在这里可能做错了什么。

如果您看到下面的 JSON 对象,它应该有一个 user 值,表示创建帖子的用户。您将在下面的帖子模型中看到,应该创建用户值,但没有。

我做错了什么?

这是创建新帖子后的 JSON 对象

{
    __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 中缺少 user 字段,尽管它是在下面的 Post 模型中创建的?

这是我的帖子模型:

// 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);
            })

    }
};

有谁知道我的关联设置是否不正确,这就是为什么我没有让任何实际帖子或用户出现在他们各自的字段中的原因?

看来我的服务器端控制器正在正确触发,因为帖子实际上是创建的。但是这些关联本身并没有联系起来,我不确定我做错了什么。

【问题讨论】:

  • 你的req.body 是什么?您是否假设创建Post 时User 应该自动更新?
  • @cdbajorin 你是 100% 正确的,我错误地认为猫鼬会为我做一些关联,并且未能将我的新消息推送到我的 user.posts,并更新 post.user 以反映用户 ID。我几乎找到了解决方案,一旦完成,我将在这里发布我是如何解决的!感谢您花时间阅读!

标签: javascript node.js mongoose one-to-many mean-stack


【解决方案1】:

我只是在下面添加一个简单的答案来跟进上面的示例。从本质上讲,@cdbajorin 是正确的,我心不在焉地认为有一些自动化正在进行,并且没有适当地遵循正确的 mongoose 命令来实现我想要的结果。

我的问题的解决方法如下:

  1. 在用户模型中,将 UserSchema posts 属性更新为空数组,而不是 mongoose.Schema.Types.ObjectID,因为无论如何这里都没有存储对象 ID,我误解了它的工作原理。

代码:

posts: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Post'
}],

相反,应该写成:

posts: [],
  1. newPost 方法,在服务器控制器中,应修改如下(请参阅 cmets inline 进行说明):

    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 集合中的文档本身,其次,作为UserSchema 中posts 数组中的对象。

更好的解决方案是将帖子作为唯一文档保留在 posts 集合中,但将会话信息中的用户 ID 添加到其中。然后,如果出于某种原因需要所有用户的帖子,则基于 userID 对 Posts 集合的查询将返回分配有该 userID 的所有帖子。然后,数据库中只存在一份帖子副本,而不是两份。

** 附加说明:修改现有文档的另一种方法是使用实​​例方法,其中将实际方法插入到用户模型(架构)文件中,并在需要时调用:

例如,在上面的UserSchema 模型中的module.exports 行之前插入以下代码,可以在需要时方便地访问此功能:

UserSchema.methods.addPost = function(post) {
    this.posts.push(post);
    this.save();
    return true;
};

要从我们的服务器控制器调用这个实例方法,我们可以重写我们的控制器如下:

User.findById(req.session.userID)
    .then(function(user) {
     // call our instance method above:
        user.addPost(newPost);
        return res.json(newPost);
     });

帖子将通过实例方法推送和保存,该方法已内置在实例对象本身中。

【讨论】:

    猜你喜欢
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2013-11-21
    相关资源
    最近更新 更多