请教一个Nodejs Mongoose问题

请教一个Nodejs Mongoose问题

UserSchema = new Schema({

name: String,

password: String

})

var User = mongoose.model(‘User’, UserSchema)

PostSchema = new Schema({

title: String,

body: String,

user: {type : Schema.ObjectId, ref : ‘User’}

});

var Post = mongoose.model(‘Post’, PostSchema);

app.get(’/posts’, function(req, res, next){

var user = new User({name: ‘lentg’, password: ‘123’});

var post = new Post({title: ‘hello’, body: ‘world’, user: user});

console.log(post.user); 这里输出为的用户是user._id, 在别的例子中输出的都是 user对象,想问一下这是怎么回事啊?

});


4 回复

当然可以!你提到的问题是关于在创建一个新的 Post 文档时,post.user 的输出结果。让我们详细解释一下这个问题,并提供一些示例代码。

问题分析

在你的代码中,post.user 是一个引用到 User 模型的 ObjectId。当你创建一个新的 Post 文档时,你传递了一个 User 对象给 user 字段。然而,Mongoose 会自动将这个 User 对象的 _id 转换为 ObjectId 类型,并存储在 Post 文档中。

示例代码

首先,我们来看一下完整的代码:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义 User 模型
const UserSchema = new Schema({
    name: String,
    password: String
});

const User = mongoose.model('User', UserSchema);

// 定义 Post 模型
const PostSchema = new Schema({
    title: String,
    body: String,
    user: { type: Schema.Types.ObjectId, ref: 'User' }
});

const Post = mongoose.model('Post', PostSchema);

// 创建一个新的 User 对象
const user = new User({ name: 'length', password: '123' });

// 创建一个新的 Post 对象并传递 user 对象
const post = new Post({ title: 'hello', body: 'world', user: user._id }); // 注意这里传递的是 user._id

// 保存 user 和 post 到数据库
Promise.all([user.save(), post.save()])
    .then(() => {
        console.log('User and Post saved successfully.');
        return Post.findOne({ title: 'hello' }).populate('user');
    })
    .then(post => {
        if (post) {
            console.log(post.user); // 输出的是完整的 User 对象
        }
    })
    .catch(err => {
        console.error(err);
    });

解释

  1. 定义模型

    • UserSchemaPostSchema 分别定义了 UserPost 的结构。
    • PostSchema 中的 user 字段是一个引用到 User 模型的 ObjectId
  2. 创建对象

    • 创建一个新的 User 对象并保存到数据库。
    • 创建一个新的 Post 对象时,传递的是 user._id 而不是整个 user 对象。这样做的原因是 Post 模型中的 user 字段期望的是一个 ObjectId 类型。
  3. 保存到数据库

    • 使用 Promise.all 同时保存 userpost
    • 通过 .populate('user') 方法查询 Post 并获取完整的 User 对象。
  4. 输出结果

    • 在控制台中,post.user 将输出完整的 User 对象,而不是仅包含 _id 的部分。

希望这个示例代码和解释能帮助你理解为什么 post.user 的输出结果是 user._id,以及如何通过 .populate() 方法获取完整的 User 对象。


如果不populate的话就是只输出子文档的_id

谢谢,了解了。

在你的代码中,post.user 输出的是 user._id 而不是 user 对象本身,这是因为你在创建 post 时,传递了一个未保存的 user 实例给 user 字段。Mongoose 默认不会将整个 user 对象嵌入到 post 中,而是将其 _id 嵌入进去,并且会引用对应的 User 模型。

如果你希望在 post.user 中得到完整的 user 对象,你需要先保存 user 到数据库,然后再在创建 post 时引用这个已保存的 user._id。以下是一个修改后的示例:

const UserSchema = new Schema({
    name: String,
    password: String
});

const User = mongoose.model('User', UserSchema);

const PostSchema = new Schema({
    title: String,
    body: String,
    user: { type: Schema.Types.ObjectId, ref: 'User' }
});

const Post = mongoose.model('Post', PostSchema);

app.get('/posts', async (req, res, next) => {
    try {
        let user = new User({ name: 'lentg', password: '123' });
        await user.save(); // 保存 user

        let post = new Post({ title: 'hello', body: 'world', user: user._id }); // 使用 user._id
        await post.save(); // 保存 post

        const loadedPost = await Post.findById(post._id).populate('user'); // 加载 post 并填充 user
        console.log(loadedPost.user); // 现在 user 是一个完整的对象
        res.json(loadedPost);
    } catch (error) {
        next(error);
    }
});

在这个示例中:

  1. 首先保存 user
  2. 创建 post 时使用 user._id
  3. 最后使用 .populate('user') 方法来加载完整的 user 对象。
回到顶部