[英]Mongoose document references with a one-to-many relationship
我正在为一个新项目设计数据库结构,我对 MongoDB 很陌生,显然是 Mongoose。
我读过 Mongooses population文档,它有一个一对多的关系,一个Person
文档到许多Story
文档,但让我感到困惑的部分是Story
文档不是引用它所属的Person
文档, Person
schema 有它的设置,因此它有一系列它“拥有”的Story
文档。
我正在设置与此非常相似的东西。 但我一直认为在创建新的Story
文档时使用Person
文档 ID 会更容易。 但也许那只是因为我更熟悉使用连接的 MySQL 关系。
如果这是最好的方法(我确信它是,因为它在文档中),当创建新的Story
文档时,更新它所属的关联People
文档中的故事数组的最佳方法是什么? 我看了但找不到任何更新现有文档以添加对其他文档的引用(或为此删除它们)的示例
我确定这是一个我刚刚忽略的简单解决方案,但任何帮助都会很棒。 谢谢!
参考population ,这里从 Mongoose 中摘录一个例子。
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._id
存储在Story._creator
中。 当你找到一个Story
的文档时,你可以使用populate()
方法来定义同时检索Person
模型中的哪个属性,例如:
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);
});
我相信这就是您要找的。 或者,您可以改用嵌套集合。
之前对这个问题的回答很有帮助,但看到更详细的代码可能会有用。 下面的代码来自我的应用程序的 Express.js 后端。 我的应用程序允许用户撰写评论。 当查询用户时,我返回用户所做的所有评论。
用户模型.js
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
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
// . . .
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
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 });
});
};
正如人口文件所说
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);
});
单向或双向关系
您可能会考虑另一种可能性:您真的需要双向关联吗? 或者仅将_creator
存储在每个Story
中就足够了吗? 并且不要存储每个Person
list of stories
。 仍然可以在搜索中查询故事列表:
let allStoriesOfOneCreator = Stories.find({_creator: person._id});
最后,这取决于您的应用程序的要求。 您多久需要一次创作者的故事?
这是创建一对多关系的好方法。
const mongoose = require("mongoose");
const Comment = mongoose.model(
"Comment",
new mongoose.Schema({
username: String,
text: String,
createdAt: Date
})
);
module.exports = Comment;
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;
const createComment = function(tutorialId, comment) {
return db.Comment.create(comment).then(docComment => {
console.log("\n>> Created Comment:\n", docComment);
return db.Tutorial.findByIdAndUpdate(
tutorialId,
{ $push: { comments: docComment._id } },
{ new: true, useFindAndModify: false }
);
});
};
// 如果你是类型脚本用户那么:
import mongoose from 'mongoose';
interface PromotionAttrs {
price: number;
startDate: Date;
endDate: Date;
}
export interface PromotionDoc extends mongoose.Document {
price: number;
startDate: string;
endDate: string;
}
interface PromotionModel extends mongoose.Model<PromotionDoc> {
build(attrs: PromotionAttrs): PromotionDoc;
}
const promotionSchema = new mongoose.Schema({
price: {
type: Number,
},
startDate: {
type: mongoose.Schema.Types.Date,
},
endDate: {
type: mongoose.Schema.Types.Date,
},
});
promotionSchema.statics.build = (attrs: PromotionAttrs) => {
return new Promotion(attrs);
};
const Promotion = mongoose.model<PromotionDoc, PromotionModel>(
'Promotion',
promotionSchema
);
export { Promotion };
import mongoose from 'mongoose';
import { PromotionDoc } from './promotion';
interface ProductAttrs {
name: string;
promotions?: PromotionDoc[];
}
interface ProductModel extends mongoose.Model<ProductDoc> {
build(attrs: ProductAttrs): any;
}
interface ProductDoc extends mongoose.Document {
name: string;
promotions?: PromotionDoc[];
}
const productSchema = new mongoose.Schema({
promotions: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Promotion',
},
],
});
productSchema.statics.build = (attrs: ProductAttrs) => {
return new Product(attrs);
};
const Product = mongoose.model<ProductDoc, ProductModel>(
'Product',
productSchema
);
export { Product };
const product = await Product.findById(productId);
if (!product) {
throw new NotFoundError();
}
const promotion = Promotion.build({
price,
startDate,
endDate,
});
await promotion.save();
product.promotions?.push();
await product.save();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.