说我有一个模型Book
和另一个模型Genre
。创建图书时,我希望能够传递一个Genre
ID并让模型自动获取并嵌入文档。例如:
const bookSchema = new Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
genre: {
type: ObjectId,
required: true,
}
});
const genreSchema = new Schema({
name: {
type: String,
required: true,
},
});
然后我要制作一本书,如下所示:
const Book = await Book.create({
title: 'Lord of the Rings',
author: 'J. R. R. Tolkien',
genre: '5d6ede6a0ba62570afcedd3a',
});
这将创建一本书,并自动根据给定ID嵌入类型文档。有没有一种方法可以从模式内部完成,还是必须将其包装在其他逻辑中?
答案 0 :(得分:4)
您可以使用预先保存的猫鼬middleware/hook查找类型,并将其设置为嵌入式文档。在猫鼬预保存钩子中,this
将是当前文档,您可以在将该值写入数据库之前读取该值并将其设置为this
对象。
请注意,由于这是一个前 save 挂钩,因此它将仅在Model.create()
或document.save()
上运行。因此它将不会在Model.insertMany()
上运行。 但是将在您使用document.save()
更新文档时运行。如果只想在新文档上设置类型,则必须检查this.isNew
属性
const { Schema, Types } = mongoose
const genreSchema = new Schema({
name: {
type: String,
required: true,
},
});
const Genre = mongoose.model('Genre', genreSchema)
const bookSchema = new Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
genreId: {
type: Schema.Types.ObjectId,
required: true,
},
genre: {
type: genreSchema,
},
});
bookSchema.pre('save', async function() {
if (this.isNew) { // this.isNew will be true on only new documents
this.genre = await Genre.findById(this.genreId) // `this` is the new book document
}
})
const Book = mongoose.model('Book', bookSchema)
/* Test book creation */
const genre = await Genre.create({
name: 'Fantasy'
})
const book = await Book.create({
title: 'Lord of the Rings',
author: 'J. R. R. Tolkien',
genreId: genre._id,
});
console.log(book)
答案 1 :(得分:1)
您可以使用混合模式类型和文档中间件来解决您的问题。请参见下面的示例代码:
const genreSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
});
const Genre = mongoose.model('Genre', genreSchema);
const bookSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
genre: {
type: Object,
required: true,
}
});
bookSchema.pre('save', async function () {
const genreID = mongoose.Types.ObjectId(this.genre);
this.genre = await Genre.findById(genreID);
});
const Book = mongoose.model('Book', bookSchema);
const newBook = new Book({ title: 'The book', author: 'xyz', genre: '5ef55c67be27fb2a08a1131c' });
newBook.save();
答案 2 :(得分:0)
您如何知道要嵌入哪个流派ID?您可以从前端发送此邮件吗?
如果是,则只需从前端选择类型ID,然后将其传递到API的请求正文中即可。
在后端时:
router.route('/book')
.post((req, res) => {
Book.create({
title: req.body.title,
author: req.body.author,
genre: req.body.genre,
}, (err, product) => {
if (err) {
res.send(err);
} else {
res.json({success:true})
}
});
})
执行类似的操作以在Book集合中创建一个新的book对象。
答案 3 :(得分:-1)
如果我正确理解了您的问题,我认为您正在寻找的是人口。 https://mongoosejs.com/docs/populate.html
它将更改您的架构,使其类似于以下内容
const bookSchema = new Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
genre: {
type: Schema.Types.ObjectId,
ref: 'Genre',
required: true,
}
});
const genreSchema = new Schema({
name: {
type: String,
required: true,
},
});
当您拿到书时,您可以通过这样做来参考类型
Book.find()
.populate('genre')
希望能回答您的问题!