Reputation: 1478
I'm learning mongoose and need some help. I have 3 collections, and on a single API call, I want to create 3 documents that reference each other; "joins" below:
Question: I know that I can do a model.create() and pass in the new document in each callback, and then update to the respective docs, but I was wondering if there's a cleaner way of doing it?
Sorry if I'm not clear on the question. Please ask me if something doesn't make sense.
Code
var chirpSchema = new mongoose.Schema({
date_created: { type: Date, default: Date.now }
, content: { post : String }
, _video: { type: $oid, ref: "video" }
, _author: { type: $oid, ref: "user" }
});
var chirp = mongoose.model('chirp', chirpSchema);
var userSchema = new mongoose.Schema({
date_joined: { type : Date, default: Date.now }
, cookie_id: String,
chirp_library: [{type: $oid, ref: "chirp"}]
})
var user = mongoose.model('user', userSchema);
var videoSchema = new mongoose.Schema({
date_tagged: { type : Date, default: Date.now }
, thumbnail_url : String
, _chirps: [{type: $oid, ref: "chirp" }]
});
var video = mongoose.model('video', videoSchema);
Upvotes: 1
Views: 172
Reputation: 6153
Mongo and other NoSQL databases aren't just an interchangeable alternative to a SQL database. It forces you to rethink your design in a different way. The concept isn't to define a relationship. The idea is to make information available in less queries. Arrays are generally a thing to avoid in Mongo, especially if they have the potential to grow infinitely. Based on your naming, that seems like a strong possibility. If you keep the rest of your schema and just delete those two arrays off of your user and video schemas:
chirp.find({_author: yourUserId}).populate("_author")
gives you the same information as user.findOne({_id: yourUserId})
in your current design.
similarly,
chirp.find({_video: yourVideoId}).populate("_video")
and video.findOne({_id: yourVideoId})
The only issue with this is that the .populate()
is running on every single chirp you are pulling. A way around this is to denormalize some (or all) of your author and video documents on the chirp document. How I would likely design this is:
var chirpSchema = new mongoose.Schema({
date_created: { type: Date, default: Date.now },
content: {
post : String
},
_author: {
_id: { type: $oid, ref: "video" },
date_joined: { type: Date, default: Date.now }
},
_video: {
_id: { type: $oid, ref: "user" },
date_tagged: { type: Date, default: Date.now },
thumbnail_url: String
}
});
var userSchema = new mongoose.Schema({
date_joined: { type : Date, default: Date.now }
, cookie_id: String
})
var videoSchema = new mongoose.Schema({
date_tagged: { type : Date, default: Date.now }
, thumbnail_url : String
});
It's perfectly OK to have data repeated, as long as it makes your queries more efficient. That being said, you need to strike a balance between reading and writing. If your user information or video information changes regularly, you'll have to update that data on each chirp document. If there is a specific field on your video/author that is changing regularly, you can just leave that field off the chirp document if it's not necessary in queries.
Upvotes: 1