如何使用 Mongoose 创建遵循模型的嵌入式文档?

Posted

技术标签:

【中文标题】如何使用 Mongoose 创建遵循模型的嵌入式文档?【英文标题】:How to create an embedded document that follows a model with Mongoose? 【发布时间】:2016-09-28 23:33:42 【问题描述】:

我有两个模型,PostComment

我的Post 模型(models/post.js):

var mongoose = require('mongoose');
var Comment = require('../models/comment');
var Schema = mongoose.Schema;

module.exports = mongoose.model('Post', new Schema(
    text: type: String, trim: true,
    postedBy: String,
    comments: [Comment]
));

我的Comment 模型(models/comment.js):

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

module.exports = mongoose.model('Comment', new Schema(
    user: String,
    comment: type: String, trim: true,
    created: type: Date, default: Date.now(), select: false
));

当我尝试创建一个没有任何comments 的新帖子时,帖子创建得非常好。

虽然当我在创建后尝试$push 对帖子发表评论时,没有任何反应。

Post.findOneAndUpdate(
    "_id": req.params.id, 
    $push: comments: 
        comment: "Hello World",
        user: "933ujrfn393r"
    
).exec(function(err, post) 
    console.log(post);
    res.json(success: true);
);

为什么无法将评论推送到帖子?我的console.log(post) 行只记录undefined,所以不太清楚这里发生了什么。我尝试了Post.findOne("_id": req.params.id)的简单测试,它成功返回了帖子,所以find查询没有问题。

【问题讨论】:

不要为此使用两个不同的集合,而是使用单个集合,在该集合中,您可以分别为字段 cmets 定义架构。 【参考方案1】:

基于this question,我相信您的问题是您嵌入的是Comment Model 而不是Comment Schema

尝试将post.js 更改为:

var Comment = require('../models/comment');

到:

var Comment = require('../models/comment').schema;

查看 Mongoose docs 关于子文档的示例后,这也很有意义。

附: 帮助我调查此问题的是输出exec 回调的err 对象以查看实际发生的情况...

【讨论】:

这可行,但创建模型也会在数据库中创建一个单独的集合。如果您不使用模型,那么首先从模式中实例化模型是没有意义的。【参考方案2】:

内嵌子文档

您的使用意味着模型中嵌入了sub document,它只需要为子文档定义schema。这会将两个模式存储在 MongoDB 的单个集合中的单个文档中

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

var CommentSchema = new Schema(
    user: String,
    comment: type: String, trim: true,
    created: type: Date, default: Date.now(), select: false
);

var PostSchema = new Schema(
    text: type: String, trim: true,
    postedBy: String,
    comments: [CommentSchema]
);

module.exports = mongoose.model('Post', PostSchema);

然后像你一样创建 cmets。

Post.findOneAndUpdate(
    "_id": req.params.id, 
    $push: comments: 
        comment: "Hello World",
        user: "933ujrfn393r"
    
).then(function (post) 
    console.log(post);
    res.json(success: true);
);

文档参考

如果您想保留这两个模型,则需要在 Post 架构中使用引用。这将在 MongoDB 的单独集合中创建单独的文档,并使用 _id 查找第二个文档。

var PostSchema = new Schema(
    text: type: String, trim: true,
    postedBy: String,
    comments: 
      type: mongoose.Schema.Types.ObjectId, 
      ref: 'Comment'
    
);

然后需要创建 cmets 才能在 Post 模型中引用它们。

c = new Comment( comment: 'x' )
c.save().then(function (result) 
  return Post.findOneAndUpdate(
     _id: req.params.id ,
     $push:  comments: result._id  
  );
).then(function (result) 
  console.log('updated post');
);

Population 可用于轻松检索“外来”文档。

【讨论】:

如果使用您提到的第一种方法(每种方法不同,尽管文档相同),我将如何将评论保存到 post 文档?我尝试创建新评论,例如c = new Comment( comment: 'x' ),然后将$pushing 到Post,虽然它似乎没有推动任何东西...... new Comment 仅适用于 Comment 是模型的第二种方法。当 cmets 只是一个 Schema 和嵌入式文档时,查询应该像您在问题中那样工作。请注意,模式和模型在 Mongoose 中是分开的。

以上是关于如何使用 Mongoose 创建遵循模型的嵌入式文档?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Mongoose 中更改文档子数组的对象内的布尔值?

如何在不创建 Mongoose 模型的情况下将 GraphQL 与 Mongoose 和 MongoDB 一起使用

Mongoose - 如何防止 mongoose 在模型实例化时创建 _id

使用 Mongoose 和 Express 创建嵌入式文档

mongoose - 数据关系模型

Node JS mongoose 创建博文评论系统