如何在 MongoDB/Mongoose 中从另一个集合引用子集合?

huangapple go评论68阅读模式
英文:

How to refer to a sub collection from another collection in MongoDB/Mongoose?

问题

在这个集合中,是否有一种方式可以定义一个字段,用来引用子文档,以创建引用特定子文档的记录?或者我应该只使用一个字符串字段,并将子文档的ID存储在其中?

希望在Report集合中的记录中得到类似以下的结果:

{
	"_id" : ObjectId("63bc482afde665158cd71a41"),
	"createdBy" : ObjectId("63b9d635e6225fa0ff29f316"),
	"parent" : ObjectId("63bbac19fde665158cd718e9"),
	"child" : ObjectId("63ba83eef2f128e2f8e69140"),
// 其他属性
}
英文:

I have a collection in mongo, let's call it Parent, with a property called children, something like this

const ParentSchema = mongoose.Schema({
children: [{
//children properties
}],
//other collection properties

When I save a record in this collection, every child gets an objectId like this

"_id" : ObjectId("63ba8421f2f128e2f8e6916d")

Then I have a collection called Report. In this collection I can refer to Parent like this

const ReportSchema = mongoose.Schema({
    parent: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Parent",
        required: false
    },

is there a way to define in this collection a field that refers to children, in order to create a record referring to a specific child? Or should I just use a string field and store the child id in there?

The idea would be to endup with records in Report like

{
	"_id" : ObjectId("63bc482afde665158cd71a41"),
	"createdBy" : ObjectId("63b9d635e6225fa0ff29f316"),
	"parent" : ObjectId("63bbac19fde665158cd718e9"),
	"child" : ObjectId("63ba83eef2f128e2f8e69140"),
// other properties
}

答案1

得分: 1

Mongoose的ref属性对此无效,因为它接受一个模型名称、模型或返回模型名称或模型的函数,但您没有对子文档进行建模(这样做会暗示将它们存储在单独的集合中,而不是作为父文档上的数组)。

您仍然可以拥有一个childId字段,其类型为ObjectId,并将子文档的ID放在那里(您说是字符串,但ObjectId更合适),而不将其声明为ref,即

const ReportSchema = mongoose.Schema({
  parent: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Parent",
    required: false
  },
  child: mongoose.Schema.Types.ObjectId,
}

但是,您将无法使用populate()来填充child字段,因为mongoose的填充功能要求存在单独的Child模型/集合。

当然,您可以填充父字段,然后编写代码来从填充的父文档的children数组中提取子文档。您还可以编写自定义聚合管道,在数据库端执行此操作。

但您最好的选择可能是坚持不懈地创建一个ChildSchema,一个Child模型,在Parentchildren数组中使用它作为ref,然后您还可以在ReportSchema中的child字段中使用它作为ref,这样mongoose的填充功能将适用于它。

英文:

Mongoose's ref property won't work for this, since it takes a model name, a Model, or a function that returns a model name or model but you aren't modeling children (doing so would imply storing them in a separate collection, not as an array on parent documents).

You can still just have a childId field of ObjectId type and put the child's ID there (you said string, but ObjectId is more appropriate) without declaring it as a ref, i.e.

const ReportSchema = mongoose.Schema({
  parent: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Parent",
    required: false
  },
  child: mongoose.Schema.Types.ObjectId,
}

However you wouldn't be able to populate() the child field since mongoose's populate features would require there to be a separate Child model/collection.

You would of course be able to populate the parent field, then write code to pull the child document out of the populated parent's children array. You could also write a custom aggregation pipeline to do this on the DB side of the wire.

But your best best may be to bite the bullet and make a ChildSchema, a Child model, use that as a ref in Parent's children array, and then you can also use it as a ref for a child field in ReportSchema and mongoose's population features will work for it.

答案2

得分: -1

"为了良好的实践,我更喜欢在报告模式中添加 ParentId,而不需要将所有子项的ID存储在父项中。如果数据量大,可能会导致问题。

const ParentSchema = mongoose.Schema({
    //其他集合属性
})
const ReportSchema = mongoose.Schema({
    parent: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Parent",
        required: true
    },
    
    //其他键
})

"

英文:

For good practice, I'll prefer add ParentId in the Report Schema no need to store the all child id in the parents

if data will be large it may create issue..

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const ParentSchema = mongoose.Schema({
//other collection properties
})

<!-- end snippet -->

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const ReportSchema = mongoose.Schema({
    parent: {
        type: mongoose.Schema.Types.ObjectId,
        ref: &quot;Parent&quot;,
        required: true
    },
    
    // other keys
  })

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年1月10日 00:56:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75060559.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定