乐闻世界logo
搜索文章和话题

How to references with a one to many relationship in mongoose

7 个月前提问
3 个月前修改
浏览次数34

6个答案

1
2
3
4
5
6

在Mongoose中,实现一对多关系通常涉及两个模型:父模型(例如“用户”)和子模型(例如“评论”),其中父模型会引用多个子模型的实例。以下是如何在Mongoose中实现这样的一对多关系:

首先,定义子模型的schema,例如评论模型:

javascript
const mongoose = require('mongoose'); const { Schema } = mongoose; const commentSchema = new Schema({ text: String, createdAt: { type: Date, default: Date.now }, // 其他字段... }); const Comment = mongoose.model('Comment', commentSchema);

接着,定义父模型的schema,并使用数组字段来引用子模型的ObjectId。Mongoose中的ref关键字用来指定引用的模型名称:

javascript
const userSchema = new Schema({ username: String, email: String, comments: [ { type: Schema.Types.ObjectId, ref: 'Comment' } ] // 其他字段... }); const User = mongoose.model('User', userSchema);

在这个例子中,每个用户可以有多个评论,用户模型中的comments字段是一个数组,存储了指向Comment模型document的ObjectId。

当需要查询用户及其相关的评论时,可以使用populate()函数来自动替换这些ObjectId为对应的评论文档:

javascript
User.findById(userId) .populate('comments') .exec((err, user) => { if (err) { // 处理错误... } console.log(user.comments); // 这里的comments将会是Comment的文档数组 });

在实际应用中,还可以进一步为populate()函数指定需要的字段,或者对结果进行排序、过滤等操作。

这样的引用关系是灵活的,因为可以独立地添加或删除评论,而不需要修改用户文档。同时,也能够轻松地查询到与特定用户相关的所有评论。不过,需要注意的是,如果一对多的关系中“多”的一方数量非常大,那么可能需要考虑分页或限制引用的数量,以避免性能问题。

2024年6月29日 12:07 回复

参考population,这里摘取Mongoose的一个例子。

shell
var mongoose = require('mongoose') , Schema = mongoose.Schema var personSchema = Schema({ _id : Schema.Types.ObjectId, name : String, age : Number, stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); var storySchema = Schema({ _creator : { type: Schema.Types.ObjectId, ref: 'Person' }, title : String, fans : [{ type: Schema.Types.ObjectId, ref: 'Person' }] }); var Story = mongoose.model('Story', storySchema); var Person = mongoose.model('Person', personSchema);

Story因此,有关模型商店的示例Person._idStory._creator. 当找到 的文档时Story,可以使用populate()方法来定义要Person同时检索模型中的哪个属性,例如:

shell
Story.findOne({_id: 'xxxxxxx'}).populate('person', 'name age').exec(function(err, story) { console.log('Story title: ', story.title); console.log('Story creator', story.person.name); });

我相信这就是您所寻找的。或者,您可以改用嵌套集合

2024年6月29日 12:07 回复

这个问题的先前答案很有帮助,但查看更详细的代码可能会很有用。以下代码来自我的应用程序的 Express.js 后端。我的应用程序允许用户撰写评论。当查询用户时,我返回用户所做的所有评论。

用户模型.js

shell
import mongoose, { Schema } from 'mongoose'; const UserSchema = new Schema({ firstname: String, lastname: String, username: { type: String, unique: true }, reviews: [{ type: Schema.Types.ObjectId, ref: 'Review' }], }, { toJSON: { virtuals: true, }, }); const UserModel = mongoose.model('User', UserSchema); export default UserModel;

review_model.js

shell
import mongoose, { Schema } from 'mongoose'; const ReviewSchema = new Schema({ body: String, username: String, rating: Number, }, { toJSON: { virtuals: true, }, }); const ReviewModel = mongoose.model('Review', ReviewSchema); export default ReviewModel;

review_controller.js

shell
// . . . export const createReview = (req, res) => { const review = new Review(); review.username = req.body.username; review.rating = req.body.rating; review.body = req.body.body; review.save() .then((result) => { User.findOne({ username: review.username }, (err, user) => { if (user) { // The below two lines will add the newly saved review's // ObjectID to the the User's reviews array field user.reviews.push(review); user.save(); res.json({ message: 'Review created!' }); } }); }) .catch((error) => { res.status(500).json({ error }); }); };

用户控制器.js

shell
export const createUser = (req, res) => { const user = new User(); user.username = req.body.username; user.email = req.body.email; user.save() .then((result) => { res.json({ message: 'User created!', result }); }) .catch((error) => { res.status(500).json({ error }); }); }; // . . . // returns the user object associated with the username if any // with the reviews field containing an array of review objects // consisting of the reviews created by the user export const getUser = (req, res) => { User.findOne({ username: req.params.username }) .populate('reviews') .then((result) => { res.json(result); }) .catch((error) => { res.status(500).json({ error }); }); };
2024年6月29日 12:07 回复

正如人口文档中所说

shell
var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 }); aaron.save(function (err) { if (err) return handleError(err); var story1 = new Story({ title: "Once upon a timex.", _creator: aaron._id // assign the _id from the person }); story1.save(function (err) { if (err) return handleError(err); // thats it! }); //then add story to person aaron.stories.push(story1); aaron.save(callback); });
2024年6月29日 12:07 回复

这是创建一对多关系的好方法。

  1. 首先,我们在Comment.js中定义Comment模型。

    const mongoose = require("mongoose");

    const Comment = mongoose.model( "Comment", new mongoose.Schema({ username: String, text: String, createdAt: Date }) );

    module.exports = Comment;

  2. 在Tutorial.js中,添加注释数组,如下所示:

    const mongoose = require("mongoose");

    const Tutorial = mongoose.model( "Tutorial", new mongoose.Schema({ title: String, author: String, images: [], comments: [ { type: mongoose.Schema.Types.ObjectId, ref: "Comment" } ] }) );

    module.exports = Tutorial;

  3. 在server.js中,添加createComment函数。

    const createComment = function(tutorialId, comment) { return db.Comment.create(comment).then(docComment => { console.log("\n>> Created Comment:\n", docComment);

    shell
    return db.Tutorial.findByIdAndUpdate( tutorialId, { $push: { comments: docComment._id } }, { new: true, useFindAndModify: false } );

    }); };

2024年6月29日 12:07 回复

单向或双向关系

您可能会考虑另一种可能性:您_真的_需要双向关联吗?_creator或者只将其存储在每个中就足够了Story。并且不要_存储_for list of storiesevery Person。故事列表仍然可以在搜索中查询:

shell
let allStoriesOfOneCreator = Stories.find({_creator: person._id});

https://docs.mongodb.com/manual/tutorial/model-referenced-one-to-many-relationships- Between-documents/

最终这取决于您的应用程序的要求。您多久需要一次创作者的故事?

2024年6月29日 12:07 回复

你的答案