Reputation: 167
Working on a database structure for a new project, and trying to figure out how exactly one-to-many relationships in MongoDB / mongoose work.
So considering a following simple structure :
I have a project table/schema with multiple images linked to it:
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'
}]
});
And then an image table/schema:
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'
}
});
I want one-to-many between images and projects, so I save an image with a project id:
const image = new Image(
{
project: project._id,
_id: new mongoose.Types.ObjectId(),
url: 'https://someurl',
});
await image.save();
If I then find this image, and populate the project field - it contains all the project's info nicely, BUT if I find this project, it doesn't have anything in the images array (referencing Image):
images: [{
type: Schema.Types.ObjectId, ref: 'Image'
}]
I thought that with ref you're creating the foreign key reference between Project and Image and then both Image should have the linked Project and Project should see the linked image in the array. Is that not the case or am I missing something here ?
Upvotes: 1
Views: 2962
Reputation: 17858
You should be able to populate images from project with no problem.
Let's say you have this project document:
{
"_id" : ObjectId("5e592a438b93764a40a81a96"),
"images" : [
ObjectId("5e592aba8b93764a40a81a98"),
ObjectId("5e592ac78b93764a40a81a99")
],
"name" : "Project 1",
"__v" : 0
}
And these image documents:
{
"_id" : ObjectId("5e592ac78b93764a40a81a99"),
"url" : "Url 2",
"project" : ObjectId("5e592a438b93764a40a81a96"),
"__v" : 0
},
{
"_id" : ObjectId("5e592aba8b93764a40a81a98"),
"url" : "Url 1",
"project" : ObjectId("5e592a438b93764a40a81a96"),
"__v" : 0
}
We can use the following code to populate images:
router.get("/projects/:id", async (req, res) => {
const result = await Project.findById(req.params.id).populate("images");
res.send(result);
});
This will give a result like this:
{
"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
}
So for your case, check if your project document really contains images array with the Object ids for image documents, and you populate correctly.
Also you don't need to add _id fields to the schema, mongodb will itself generate _id automatically.
project
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);
image
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);
Upvotes: 2