Mongodb multiple refrence to same field - javascript

I want to use refrence of multipe collection on the same field of mongodb mongoose schema. Is this possible?? All I want is to save object id of different collection in same field,I am doing this,but its not working correctly..
var QuizSchema = new Schema({
goal_id:{
type: Schema.ObjectId,
ref: 'Exam'||'Subject',
}
});
here its save data properly..but when I use populate method it returns null value for document which has ref to second collection ie. Subject

Even if you are able to register a reference to both Models, how do you think Mongoose will be able to populate it?
Instead, you can simply have references to both:
var QuizSchema = new Schema({
goal:{
exam: {type:ObjectId, ref:'Exam'},
subject: {type: ObjectId, ref: 'Subject'}
}
});
This will even make it convenient to read after population.

Related

Mongoose: Reference schema in properties or add as an array? which is better

For example if i have two schemas User and Post , should i add User reference in Post's properties, or add Post schema as an array inside User Schema? which is better performance wise( and other aspects).
var PostSchema = new mongoose.Schema({
title: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
});
OR
var UserSchema = new mongoose.Schema({
name: String,
posts: [PostSchema]
});
var PostSchema = new mongoose.Schema({
title: String,
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
});
I think this way is better than others.
You should have a reference to the user in the PostSchema.
This is the better approach because a user can have multiple posts and if you save the posts in the UserSchema as an array, that array can grow infinitely. This can cause problems because there's a limit on the max size of a mongodb document. Single mongodb document cannot be greater than 16Mb.
Saving Posts in the User schema is better from the performance perspective but considering the limit on the size of mongodb document and the fact that a user can have many posts, a child document (Post) referencing its parent document (User) is the better approach here.

Mongoose how to update array from child to parent

I have following schema for Audio.
const AudioSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
uploaderId: {
type: String,
required: true
}
});
Instead of referencing the User, I just store the User's _id as uploaderId.
In my User schema I also have audioFiles: [Audio] array for all audio files that user has uploaded.
const UserSchema = new mongoose.Schema({
...,
audioFiles: [Audio]
});
When I try to update my AudioSchema from my REST Api, I can change all the properties and that works, but after saving this Audio model those changes doesn't affect the User model.
Now I created a new branch and try to change uploaderId to UserSchema. But I wonder is there a solution for this without referencing the UserSchema
I managed to do this with help of MongooseArray.prototype.pull method.
Steps for solving this problem is really easy.
First I get the User that is associated with AudioModel.uploaderId, then I used the user.audioFiles.pull() method. Correct code is below.
let user = await UserService.getUser(userId);
await user.audioFiles.pull({
_id: audioId //audioId is the id which i'm trying to remove from array
});
await user.save();
I also added try-catch block to handle errors.
Anyone having this kind of issue can use the link below to get more information about MongooseArray.prototype.pull method.
Also you can check the other answers in this post.

Mongoose Populate - how can you dynamically or programmatic perform field selection

I have a query 1 which return an array of records, let's say activityList from activitySchema. Now On this activityList array, I am trying to use populate to populate user Information. I would like to dynamically select fields based on the certain activity type. Here is my schema since each sub-document has many fields.
var activitySchema = new Schema({
userId: {type: Schema.Types.ObjectId, ref: 'users'}
, updateDt: {type: Date, Default: Date.now()}
, activityType: String
, weight: Number
, activityAttributes: [String]
});
users schema has many sub-documents like
var userSchema = new Schema({
auth: authSchema
, membership: membershipSchema
, personal: personalSchema
, location: locationSchema
, religion: religionSchema});
based on the activity type value let's say "PERSONAL", "LOCATION" & "RELIGION" populate should only return those values.
Sorry, no can do with the schema you have.
You can query the activitySchema object, examine the activityType, then query the userSchema selecting only the fields you want based on the activity type: PERSONAL, LOCATION, RELIGION. So you can proceed with two queries instead of one.
You could also grab them all with populate and then filter out the props you don't want in javascript. You would still need to send all of that data over the network to your calling code. But maybe you save some bandwidth if the above code shunts the data someplace else (like a browser).
Without knowing more about what you are trying to accomplish I can't advise you on a better way to model your data. Potentially breaking up the userSchema is probably something to consider. There's no doubt that if you put in the time you can have a data model that gets you everything in one shot.

Is it possible to update an Object within a Mongoose document?

I have a weird problem with mongoose, and I'm starting to suspect that I'm doing something wrong.
My schema looks something like this:
var personSchema = mongoose.Schema({
name: String, // Self-e
info: { type: Object, default: {'value':'result'} },
created_on: { type: Date, default: Date.now }
})
After fetching the document, I've tried to edit the info object like so (pretending that person is the fetched document):
person.info['value2'] = 'result2'
person.save()
These changes don't show up in the DB, and I'm getting no errors when running it. Any ideas?
As I learned from #ippi, because info is a mixed Object, you need to make sure that Mongoose knows it was modified so that it will save when you call person.save()
For example:
person.info['value2'] = 'result2'
person.markModified('info')
person.save()

Arrays of schema types on Mongoose

I have a schema:
var s = new Schema({
links: {
type: [Url]
}
});
In this case I am using the url schema type from https://github.com/bnoguchi/mongoose-types - but I have tried this with other types. Mongoose doesn't seem to validate/use the schema type when in an array - works fine without the array.
How can I define an array of schema types that will validate?
Answer from Mongoose creator:
"Unless the Url is a subdocument, validation will not get triggered currently (there is a ticket open somewhere to support richer types). The work-around is to define validation on the array: https://gist.github.com/aheckmann/12f9ad103e0378db6afc"
I ended up creating subdocuments as Mongoose supports validation on them when in array form.
var links = new Schema({
link: URL
});
var s = new Schema({
links: {
type: [links]
}
});
Try var s = new Schema({links: [Url]});

Categories