MongoDB / Mongoose 一对多关系

Posted

技术标签:

【中文标题】MongoDB / Mongoose 一对多关系【英文标题】:MongoDB / Mongoose one-to-many relationship 【发布时间】:2020-06-12 15:44:31 【问题描述】:

为一个新项目处理数据库结构,并试图弄清楚 MongoDB / mongoose 中的一对多关系究竟是如何工作的。

所以考虑以下简单的结构:

我有一个项目表/模式,其中链接了多个图像:

const ProjectSchema = mongoose.Schema(
    _id: mongoose.Types.ObjectId, // Just the id,
    name:  type: String, required: true, trim: true,  maxLength: 60 ,
    description:  type: String, required: false , 
    images: [ 
        type: Schema.Types.ObjectId, ref: 'Image'
    ]
);

然后是图像表/模式:

const ImageSchema = new Schema(
    _id: mongoose.Types.ObjectId, // Just the id,
    url:  type: String, unique: true, required: true 
    project:  
        type: Schema.Types.ObjectId, ref: 'Project'
            
);

我想要图像和项目之间的一对多,所以我用项目 id 保存了一个图像:

const image = new Image(
        
                project: project._id,
                _id: new mongoose.Types.ObjectId(),
                url: 'https://someurl',
        );        
        await image.save();

如果我随后找到此图像并填充项目字段 - 它很好地包含所有项目信息,但如果我找到此项目,则图像数组中没有任何内容(引用图像):

images: [ 
        type: Schema.Types.ObjectId, ref: 'Image'
    ]

我认为使用 ref 您正在创建 Project 和 Image 之间的外键引用,然后 Image 应该具有链接的 Project 并且 Project 应该在数组中看到链接的图像。 不是这样还是我在这里遗漏了什么?

【问题讨论】:

如何查询项目? 【参考方案1】:

您应该能够毫无问题地从项目中填充图像。

假设你有这个项目文件:


    "_id" : ObjectId("5e592a438b93764a40a81a96"),
    "images" : [
        ObjectId("5e592aba8b93764a40a81a98"),
        ObjectId("5e592ac78b93764a40a81a99")
    ],
    "name" : "Project 1",
    "__v" : 0

还有这些图片文件:


    "_id" : ObjectId("5e592ac78b93764a40a81a99"),
    "url" : "Url 2",
    "project" : ObjectId("5e592a438b93764a40a81a96"),
    "__v" : 0
,

    "_id" : ObjectId("5e592aba8b93764a40a81a98"),
    "url" : "Url 1",
    "project" : ObjectId("5e592a438b93764a40a81a96"),
    "__v" : 0

我们可以使用下面的代码来填充图片:

router.get("/projects/:id", async (req, res) => 
  const result = await Project.findById(req.params.id).populate("images");
  res.send(result);
);

这将给出如下结果:


    "images": [
        
            "_id": "5e592aba8b93764a40a81a98",
            "url": "Url 1",
            "project": "5e592a438b93764a40a81a96",
            "__v": 0
        ,
        
            "_id": "5e592ac78b93764a40a81a99",
            "url": "Url 2",
            "project": "5e592a438b93764a40a81a96",
            "__v": 0
        
    ],
    "_id": "5e592a438b93764a40a81a96",
    "name": "Project 1",
    "__v": 0

因此,对于您的情况,请检查您的项目文档是否真的包含带有图像文档对象 ID 的图像数组,并且您正确填充。

另外你不需要在 schema 中添加 _id 字段,mongodb 会自动生成 _id。

项目

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const ProjectSchema = Schema(
  name:  type: String, required: true, trim: true, maxLength: 60 ,
  description:  type: String, required: false ,
  images: [
    
      type: Schema.Types.ObjectId,
      ref: "Image"
    
  ]
);

module.exports = mongoose.model("Project", ProjectSchema);

图片

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const ImageSchema = new Schema(
  url:  type: String, unique: true, required: true ,
  project: 
    type: Schema.Types.ObjectId,
    ref: "Project"
  
);

module.exports = mongoose.model("Image", ImageSchema);

【讨论】:

谢谢!但我的意思是 - 有这个模式结构,如果我添加一个引用项目的新图像,比如说:“项目”:ObjectId(“5e592a438b93764a40a81a96”),如果那个id的项目有这个图像自动出现在图像数组?当我查询像 const foundProject = await Project .find( name: project.name ) .populate('category status creator images') 这样的项目时,它显示空图像数组 [] @RRob 您需要填充,如我在答案中所示。此外,当您创建新图像时,您应该将该图像 ID 添加到项目的图像数组中。我已经展示了示例文档。 知道了,例如,当我创建链接到项目的新图像时,我必须始终明确地将其添加到项目中的图像数组中,对吗? @RRob 是的,这是真的。 听起来很有趣,如果你明天有空请做

以上是关于MongoDB / Mongoose 一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

mongoose - 数据关系模型

MongoDB使用基于子文档的Mongoose过滤器

MongoDB/Mongoose 一对多,在子节点中引用父节点 - 分组并加入

MongoDB 中的关联查询MongoDB : aggregate/lookup 对比 Mongoose : ref / populate

mongodb一对n关系中的两种导航

如何使用 mongoose refs 处理一对多关系