猫鼬引用子文档的不同方式?

mongoose different ways to reference subdocuments?

此语法直接来自有关子类型的 mongoose 文档。但是,我也看到了对子文档的替代引用。有什么区别?

https://mongoosejs.com/docs/subdocs.html

var childSchema = new Schema({ name: 'string' });

var parentSchema = new Schema({
  // Array of subdocuments
  children: [childSchema],
  // Single nested subdocuments. Caveat: single nested subdocs only work
  // in mongoose >= 4.2.0
  child: childSchema
});

子文档的另一种引用类型

var childSchema = new Schema({ name: 'string' });

mongoose.model('children', childSchema);

var parentSchema = new Schema({
  children: {
    type: Schema.Types.ObjectId,
    ref: 'children'
  },
});

以上两种语法完全不同,一种是实际的子文档(children)存储在父文档中,而另一种是新文档存储在children集合中,只有它的引用是存储在父文档中。

案例一:

var childSchema = new Schema({ name: 'string' });

var parentSchema = new Schema({
  // Array of subdocuments
  children: [childSchema],
  // Single nested subdocuments. Caveat: single nested subdocs only work
  // in mongoose >= 4.2.0
  child: childSchema
});

在这个给定的语法中,父文档也会将子文档存储在父文档中。

父集合中的示例文档如下所示:

{ 
  _id : "parent_random_generated_id"
  children :[{ _id : "childid1" , name : "Captain America"},
             { _id : "childid2" , name : "Iron Man"},...],
  child : {_id : "childid3" , name : "Thor Odinson"},
  ...
}

案例二:

var childSchema = new Schema({ name: 'string' });

mongoose.model('children', childSchema);

var parentSchema = new Schema({
  children: {
    type: Schema.Types.ObjectId,
    ref: 'children'
  },
});

在这种语法中,子文档将单独存储,它们引用的 id (_id) 将存储在父文档中。

本例中的示例文档如下所示:

// Children documents
{ _id : "childid1" , name : "Captain America"}
{ _id : "childid2" , name : "Iron Man"}
{ _id : "childid3" , name : "Thor Odinson"}

//parent document
{ 
  _id : "parent_random_generated_id"
  children :["childid1","childid2",...],
  child : "childid3",
  ...
}

在第二种情况下,您可以使用 Mongodb $lookup 运算符填充子文档,需要时使用 mongodb aggregation pipeline,或使用 .populate('children').populate('child') 填充特定的子文档。

我希望这能澄清你的疑问。

区别很简单。 前一个你只是为 child 定义架构 不会为 children 创建一个单独的集合在数据库中,您会将整个 child 文档嵌入到 parent.

并且在 后面的一个中,您通过调用 mongoose.model 为 child 模式定义模型,这会创建一个单独的集合数据库中 children 的 ,然后您可以在 parent 文档中引用 child 文档,而无需将整个 child 文档嵌入 parent 只需添加 child _id.

我已经完成了 案例 2 一些数据写入示例。让我们使用书籍作者场景:

const authorSchema = new Schema({ name: 'string' });
const authorModel = mongoose.model('authors', authorSchema);
    
const bookSchema = new Schema({
  title: String,
  author: {
    type: Schema.Types.ObjectId,
    ref: 'author'
  },
});

const bookModel = mongoose.model('books', bookSchema)

const authorData = { name: "John Doe" }

// Check if author does exists. Insert if not or find if yes
const options = {
  upsert: true,
  new: true,
  setDefaultsOnInsert: true
};
const anAuthor = await authorModel.findOneAndUpdate(authorData, authorData, options)

// Insert a new book with reference to `anAuthor`
const aBook = new bookModel({ title: "MyBook" })
aBook.set({ author: anAuthor })
await aBook.save()

在这种语法中,子文档将单独存储,它们引用的 id (_id) 将存储在父文档中。

本例中的示例文档如下所示:

// authors documents
{ _id : "authorId1" , name : "John Doe"}
{ _id : "authorId2" , name : "Iron Man"}
{ _id : "authorId3" , name : "Thor Odinson"}

//books document
{ 
  _id : "parent_random_generated_id"
  title: "MyBook",
  author : "authorId1",
  ...
}

对于阅读,您可以使用 populate:

let result = await bookModel.find()
result = await authorModel.populate(result, { path: 'author' })