mongoose custom id with populate? - node.js

how to use populate to select object by custom object_id so i got
const BookSchema = new mongoose.Schema({
title: {
type: String
},
description: {
type: String
}
});
module.exports = mongoose.model('Book', BookSchema)
and there is a Translation Collection
const TranslationSchema = new mongoose.Schema({
uuid:{
type:String,
required: true,
index: true
},
locale: {
type: String,
trim: true,
required: true,
index: true
},
translation: {
type: String,
default:''
}
});
module.exports = mongoose.model('Translation', TranslationSchema);
Now book in title and description has an UUID that represents Translation and i want to make .populate('title') and pass title as UUID and locale as string lets say 'en' is it even possible?

Related

How to use virtual on a nested field in mongoose

I am using mongoose in node.js. I have the following Schema.
const CustomerSchema = new mongoose.Schema({
...
email: {
type: String,
required: true,
lowercase: true,
trim: true
},
addresses: [
{
addressType: {
type: String,
enum: [ 'personal', 'shipping', 'billing' ]
},
street: {
type: String,
required: true,
trim: true
},
streetNumber: {
type: String,
trim: true
},
floor: {
type: String,
trim: true
},
apartament: {
type: String,
trim: true
},
cp: {
type: String,
required: true,
trim: true
},
district: {
type: String,
trim: true
},
city: {
type: mongoose.Schema.ObjectId,
ref: 'City',
required: true
}
}
]
});
I want to use "virtuals" to "add" a new field in every object in the array addresses?
How I can do this using virtuals? Is it possible?
I can achieve the same result using, but I would like to use virtuals.
const customerDB = await Customer.findById(idCustomer).lean()
customerDB.addresses = customerDB.addresses.map((address) => ({
...address,
addressDesc: mapTypeAddressDescription(address.addressType)
}));
Many Thanks!
As the name suggests virtuals are not added to the MongoDB documents. They are used for computed properties on documents.
Suppose you have a User model. Every user has an email, but you also want the email's domain. For example, the domain portion of 'test#gmail.com' is 'gmail.com'.
Below is one way to implement the domain property using a virtual. You define virtuals on a schema using the Schema#virtual() function.
const userSchema = mongoose.Schema({
email: String
});
// Create a virtual property `domain` that's computed from `email`.
userSchema.virtual('domain').get(function() {
return this.email.slice(this.email.indexOf('#') + 1);
});
const User = mongoose.model('User', userSchema);
let doc = await User.create({ email: 'test#gmail.com' });
// `domain` is now a property on User documents.
doc.domain; // 'gmail.com'
You should check the documentation for more details.
You can do something like this:
CustomerSchema.path('addresses').schema.virtual('fullAddr').get(function() {
return 'foo'
})
Also, it is useful to check this answer on stackoverflow if the above one doesn't work.

Can not populate array of objects

EDIT added mongoose.model.
I'm pretty new to mongodb and mongoose. I'm not able to populate books to authors in mongoose.
Can anyone help me with that? Here is my code. I removed unnecessary fields
const authorSchema = mongoose.Schema({
_id:{
type: String,
required: true,
unique: true,
trim: true
},
name: {
type: String,
required: true,
trim: true
},
books: [{
type: String,
ref: "Book"
}]
}, {_id:false})
const Author = mongoose.model('Author', authorSchema)
module.exports = {Author}
And my books schema looks as following
const bookSchema = mongoose.Schema({
_id:{
type:String,
required:true,
unique:true,
trim: true
},
name: {
type: String,
required: true,
trim: true,
unique: true
},
description:{
type: String,
trim: true,
default: 'No description specified'
},
datePublished: {
type: Date,
trim: true,
default: '01/01/2001'
},
author:{
type: String,
ref: 'Author',
required: true
}
}, {_id:false})
const Book = mongoose.model('Book', bookSchema)
module.exports = {Book}
Here is the route to populate them together
AuthorRouter.get('/authors/:id', async(req, res)=>{
const authorID = req.params.id
try {
const author = await Author.findById(authorID)
try {
const populated = await author.populate({path: 'books.book', select: 'name description -_id'})
console.log(populated);
res.status(201).send(populated)
} catch (e) {
res.status(401).send(`${e}\n Unable to populate categories`)
}
} catch (error) {
res.status(401).send('Unable to find author')
}
})
Output is following with empty books array:
{
"_id": "123",
"name": "testuser",
"books": [],
"__v": 0
}
Populating an arrays of refs works the same way as a single ref. Just call the populate method on the query and an array of documents will be returned in place of the original _id's.
In your case that would be:
const populated = await author.populate({path: 'books', select: 'name description -_id'});
Hey i have modify your code , try to use this one
This is your author schema file
const Schema = mongoose.Schema;
const authorSchema = mongoose.Schema({
_id:{
type: String,
required: true,
unique: true,
trim: true
},
name: {
type: String,
required: true,
trim: true
},
books: [{
type: Schema.Types.ObjectId,
ref: "bookSchema"
}]
}, {_id:false})
const Author = mongoose.model('Author', authorSchema)
module.exports = {Author}
And this is your route
AuthorRouter.get('/authors/:id', async(req, res)=>{
const authorID = req.params.id
try {
const author = await Author.findById(authorID)
try {
const populated = await author.find().populate('books');
console.log(populated);
res.status(201).send(populated)
} catch (e) {
res.status(401).send(`${e}\n Unable to populate categories`)
}
} catch (error) {
res.status(401).send('Unable to find author')
}
})

Mongoose - Reference a field from another table

I have two tables: Post and User and I want to reference the User name in the Post table.
I can reference the ID but I also need the name.
User model:
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
})
module.exports = mongoose.model("User", userSchema)
Post model:
const { ObjectId } = mongoose.Schema.Types
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: ObjectId,
ref: "User",
},
})
module.exports = mongoose.model("Post", postSchema)
In the doc they said:
Note: ObjectId, Number, String, and Buffer are valid for use as refs.
However, you should use ObjectId unless you are an advanced user and
have a good reason for doing so.
However I couldn't find an example on how I can do this.

How to use nested data in model class using NodeJS

I have data like ug.tutionfees andpg.tutionfees in MongoDB. How to implement this data in NodeJS model class and angular plz tell me.
My model class:
const mongoose = require('mongoose');
const UniversitySchema = mongoose.Schema({
worldranking:String,
countryranking:String,
universityname:String,
bachelorprogram:String,
masterprogram:String,
phdprogram:String,
country:String
},{collection:'us'});
const University =module.exports = mongoose.model('University',UniversitySchema);
I want to implement ug.tutionfees and pg.tutionfees in this model class.
If you have only these ug.tutionfees and pg.tutionfees are two different objects you can add into schema as below:
ug :{
tutionfees :{
type: String
}
},
pg :{
tutionfees :{
type: String
}
}
Check one of my schema structure:
'use strict'
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var rbpiSchema = new Schema({
rbpiId: {
type: String,
required: true,
unique: true
},
name: {
type: String,
required: true
},
description: {
type: String
},
last_action: {
activity: {
type: String
},
status: {
type: String
},
ut: {
type: Number
},
description: {
type: String
}
},
ct: {
type: Number,
require: true,
default: new Date().getTime()
},
ut: {
type: Number,
require: true,
default: new Date().getTime()
}
});
module.exports = mongoose.model('rbpi', rbpiSchema);

easier way to save sub-documents in separate collection in Mongoose

I've got the following data structure:
const schema = new Schema({
userId: { type: String, required: true },
image: { type: String, required: true},
name: { type: String, required: true },
description: { type: String, required: true },
subCategories: [{ type: mongoose.Schema.Types.ObjectId, ref: 'SubCategories' }]
}, {
strict: 'throw'
});
export const Plan = mongoose.model('Plan', schema);
const schema = new Schema({
userId: { type: String, required: true },
name: { type: String, required: true },
description: { type: String, required: true }
}, {
strict: 'throw'
});
export const SubCategories = mongoose.model('SubCategories', schema);
and I want to save each of the subCategories in a separate collection each time a new Plan entity is created.
This requires me to iterate the subCategories and to create each one of the sub-category.
for example:
plan.subCategories = await Promise.all(plan.subCategories.map(async (s: IWorkoutDay) => {
const sub = new SubCategories(s);
sub.userId = userId;
await sub.save();
return sub;
}));
const p = new Plan(plan);
p.userId = userId;
await p.save();
and also each time I want to edit the subCategories of the element I'm required to iterate find the element and to update each one separately.
is there an easier way to achieve this? since it seems pretty complicated to me.

Resources