Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Mongoose:创建时自动嵌入字段?_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

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
模式或自定义模式类型?设置为自定义模式。你能给你的答案加一个样本吗?