Javascript Mongoose:创建时自动嵌入字段?
假设我有一个模型,Javascript Mongoose:创建时自动嵌入字段?,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,假设我有一个模型,书,另一个模型,流派。当我创建这本书时,我希望能够传递流派ID,并让模型自动获取和嵌入文档。例如: const bookSchema=新模式({ 标题:{ 类型:字符串, 要求:正确, }, 作者:{ 类型:字符串, 要求:正确, }, 类型:{ 类型:ObjectId, 要求:正确, } }); const genreSchema=新模式({ 姓名:{ 类型:字符串, 要求:正确, }, }); 然后我想创作一本书,如下所示: const Book=wait Book.cr
书
,另一个模型,流派
。当我创建这本书时,我希望能够传递流派
ID,并让模型自动获取和嵌入文档。例如:
const bookSchema=新模式({
标题:{
类型:字符串,
要求:正确,
},
作者:{
类型:字符串,
要求:正确,
},
类型:{
类型:ObjectId,
要求:正确,
}
});
const genreSchema=新模式({
姓名:{
类型:字符串,
要求:正确,
},
});
然后我想创作一本书,如下所示:
const Book=wait Book.create({
标题:《魔戒》,
作者:“J.R.R.托尔金”,
类型:“5d6ede6a0ba62570afcedd3a”,
});
这将创建一本书,并根据给定ID自动嵌入类型文档。是否有一种方法可以从模式中执行此操作,或者我必须将其包装在其他逻辑中?如果我正确理解您的问题,我认为您要查找的是填充 它会将您的模式更改为如下所示
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')
希望这能回答你的问题 您可以使用预保存mongoose来查找流派并将其设置为嵌入文档。在mongoose pre save hook中,
此
将是当前文档,您可以读取该值并将该值设置为此
对象,然后再将其写入数据库
请注意,由于这是一个预保存钩子,因此它将仅在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)
您可以使用混合架构类型和文档中间件来解决问题。请参阅下面的示例代码:
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();
您如何知道要嵌入哪个流派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})
}
});
})
执行类似操作以在您的图书集中创建新的图书对象。否,因为我不希望在类型文档更改时更新子文档。我有一个特定的用例,其中子文档不能更改,即使原始引用也不能更改。这有意义吗?你必须用一个附加的逻辑。一种方法是使用预保存挂钩,它将在每次保存之前运行operations@thammada.ts你能举个例子说明我会怎么做吗?当我尝试在预保存钩子中设置this.genre时,它不会更改数据库中的值。是否有办法使genreId属性也称为genre?因为这是针对API的,所以我理想情况下希望能够将ID作为文档将占用的属性的名称传递。因为类型
字段中的内容将根据模式中声明的内容进行验证。如果将genre
字段指定为genreSchema
类型,则当您最初将其设置为字符串或ObjectId
时,验证将失败。您可以将genre
类型设置为Schema.Types.Mixed
,但我认为这不是一个好主意,或者您可以将Mixed
模式或自定义模式类型?设置为自定义模式。你能给你的答案加一个样本吗?