MongoDB: Populate or Query for two collections - javascript

I have the following Schemas:
let ProjectSchema = new mongoose.Schema({
title: {
type: String
},
employees: {
user: String, // ==> ObjectId of User from UserSchema
role: String,
workload: Number,
},
description: {
type: String
}
});
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true
},
name: {
type: String
},
projects: {
type: Array // ==> ObjectId of Project from ProjectSchema
}
});
What I want to achieve is to get the user by _id or email and to get also all data from his projects like:
{
"user": {
"_id": "asdf1234",
"email": "your#email.com",
"name": "Max"
"projects": {
"title": "Project 1",
"description": "Just a text",
"employees": {
"user": "asdf1234",
"role": "developer",
"workload": 40
}
}
}
}
And I also want to get a specific project by Id and the employee.user field should be populated with the correct user data.
Can I do this with Mongoose populate?
My approach would be to first do a User.findOne() and then check the project.id and to a Project.findOne().

how about in your UserSchema you reference an array of projects, that way when you query for the user you are querying for all the projects tied to the user.
let mongoose = require("mongoose");
let Projects = require("./projects");
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true
},
name: {
type: String
},
projects: {
type: [Projects.schema]
}
});
Then every time you query for the user it comes with the projects associated to the user.

Related

How can i populate a model data while fetching it?Mongodb

I have two model's schema, one of them is the Category and the other is the subCategory. We need the Category to create a subCategory model, but the Category model doesn't have to have subCategories.
This is my subCategory model:
const Mongoose = require('mongoose');
const { Schema } = Mongoose;
// Brand Schema
const SubCategorySchema = new Schema({
name: {
type: String,
required:true
},
id: {
type: Schema.Types.String,
unique:true,
required:true
},
category: {
type: Schema.Types.ObjectId,
ref: 'Category',
required:true
},
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('SubCategory', SubCategorySchema);
and this is my Category model:
const Mongoose = require('mongoose');
const { Schema } = Mongoose;
// Category Schema
const CategorySchema = new Schema({
name: {
type: String,
trim: true,
},
id: {
type: String,
required:true,
unique: true
},
image: {
type:String,
default:'http://res.cloudinary.com/wisecart/image/upload/v1616718691/kuy26lytx5k0lkvfkgrt.svg',
required:true
},
description: {
type: String,
trim: true
},
updated: Date,
created: {
type: Date,
default: Date.now
},
});
module.exports = Mongoose.model('Category', CategorySchema);
I'm using
How do I populate subcategories when I request a category?
For example, I want to get a response as
{
"image": "http://res.cloudinary.com/wisecart/image/upload/v1616718691/kuy26lytx5k0lkvfkgrt.svg",
"_id": "606605934b213d2887e3a840",
"name": "Samsung",
"description": "sama",
"id": "asa",
"subCategory": [{Subcategory with an Id of _id},{Subcategory with an Id of _id}],
"created": "2021-04-01T17:40:35.505Z",
"__v": 0
}
You've to use aggregation query
Demo - https://mongoplayground.net/p/ItN9R9AlE4A
Use $lookup
Performs a left outer join to an unsharded collection in the same database to filter in documents from the "joined" collection for processing. To each input document, the $lookup stage adds a new array field whose elements are the matching documents from the "joined" collection. The $lookup stage passes these reshaped documents to the next stage.
https://mongoosejs.com/docs/api/aggregate.html#aggregate_Aggregate
db.category.aggregate([
{
"$lookup": {
"from": "subCategory", // collection name
"localField": "_id",
"foreignField": "category",
"as": "subCategory"
}
}
])

how to populate users object with field

These the response for user that Im getting from get request to profile API
"user": "5cc3a4e8d37a7259b45c97fe"
What I'm looking for instead is
"user":{
"_id": "5cc3a4e8d37a7259b45c97fe",
"name":"Jhon Doe",
}
Here is my code:
Profile.findOne({
user: req.user.id
})
.populate('user',['name']) // I added this line to populate user object with name
.then(profile=>{
if(!profile){
errors.noprofile = 'There is no profile for this user'
return res.status(404).json(errors);
}
res.json(profile)
})
.catch(err => res.status(404).json(err));
However, Im getting these error:
{
"message": "Schema hasn't been registered for model \"users\".\nUse mongoose.model(name, schema)",
"name": "MissingSchemaError"
}
What am I missing
Profile Schema
const ProfileSchema = new Schema({
user:{
type: Schema.Types.ObjectId,
ref: 'users'
},
handle: {
type: String,
required: true,
max: 40
},
company: {
type: String
},
website: {
type: String,
}
})
Here is how my Users schema looks like
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const UserSchema = new Schema({
name:{
type: String,
required: true,
},
email:{
type: String,
required: true,
},
password:{
type: String,
required: true,
},
avator:{
type: String,
},
date:{
type: Date,
default: Date.now,
}
});
module.exports = User = mongoose.model('Users', UserSchema)
Schema that you are referencing in Profile schema is users, but you have saved your user schema as Users. So I would say that you need to update your Profile schema:
const ProfileSchema = new Schema({
user:{
type: Schema.Types.ObjectId,
ref: 'Users'
},
handle: {
type: String,
required: true,
max: 40
},
company: {
type: String
},
website: {
type: String,
}
})
Name under which is saved your User schema can be found in this line
module.exports = User = mongoose.model('Users', UserSchema)
The error says you don't have Schema for Users. You reference it from Profile Schema, but you don't have it. It can be this way:
const Users = new Schema({
name: String
})

Mongodb mongoose node js schema relation

hello i am new on mongodb and node js i have a question
here is my product schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const categorySchema = require('./category');
const ProductSchema = new Schema({
country: {
type: String,
required: [true, "country can't be null"]
},
city: {
type: String,
default: ""
},
name: {
type: String,
required: [true, "name can't be null"]
},
measureValue: {
type: Number,
default: 0
},
minPrice: {
type:Number,
required: [true, "minPrice can't be null"],
min: [1,"minPrice must be at least 1"]
},
maxPrice: {
type:Number,
required: [true, "maxPrice can't be null"],
min: [1,"maxPrice must be at least 1"]
},
photoUrl: {
type:String,
default: ""
},
explanation: {
type: String,
default: ""
},
category: [categorySchema.schema],
userID: {
type: String,
required: [true,"userid cant be null"]
},
isActive: {
type: Boolean,
default: true
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
and here is my category schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CategorySchema = new Schema({
name: {
type: String,
required: [true, "name can't be null"]
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
i need to do this;
every product data must be have category
if one day,one category's name changed then every product that relation with that category must changed
i am trying to set category id to product schema and when i fetch the data it must be comes every product with category name as json
i am really confused if you help me i'd be really thankful
You can set up your category as :
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'category' //your model name
}
You can wrap it into an array and name it categories if you want multiple categories.
Then when you get the data, you will have to execute new Product().populate('category') to get retrieve the category data instead of just returning the category ObjectId.

Why aren't my Virtual Mongoose types showing up? [duplicate]

This question already has answers here:
Can't get Mongoose virtuals to be part of the result object
(3 answers)
Closed 6 years ago.
This is my post model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = new Schema({
text: String,
image: String,
author: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
university: {
type: String,
required: true
},
uniOnly: {
type: Boolean,
required: true
},
createdAt: {
type: Number,
required: true
},
expiresAt: {
type: Number,
required: true
},
voteCount: {
type: Number,
required: true
},
comments: [{
type: Schema.Types.ObjectId,
ref: 'comment'
}],
commenters: [{
type: Schema.Types.ObjectId,
ref: 'user'
}],
categories: [{
type: String
}]
});
PostSchema.virtual('commentCount').get(function () {
return this.comments.length;
});
PostSchema.virtual('expired').get(function () {
const now = new Date().getTime();
return now <= this.expiresAt;
});
const Post = mongoose.model('post', PostSchema);
module.exports = Post;
As you can see, I'm attempting to create a couple of virtual types:
commentCount will give the length of the array of comments.
expired will either flag as true or false
Here is the controller:
create(req, res, next) {
const postProps = req.body;
const now = new Date().getTime();
const expiresAt = now + 43200000;
const { author, text, image, categories, university, uniOnly } = postProps;
Post.create({
author,
text,
image,
categories,
university,
uniOnly,
createdAt: now,
voteCount: 0,
expiresAt,
})
.then(post => res.send(post))
.catch(next);
},
Right now, using Postman I can see that the post itself is being created just fine. For some reason though, I'm not getting back anything for the virtual types, neither commentCount nor expired.
This is what I get back in response:
}
"__v": 0,
"author": "5896623ff821b14c4470cf97",
"text": "this is ANOTHER post",
"university": "University of Birmingham",
"uniOnly": false,
"createdAt": 1486306414679,
"voteCount": 0,
"expiresAt": 1486349614679,
"_id": "58973c6ef24ca4828c2adae1",
"categories": [
"music",
"dance"
],
"commenters": [],
"comments": []
}
Can you please tell me what I'm doing wrong here? I've followed along several along courses in which I've done similar before and I'm scouring through the course code. I can't work it out though.
Thank you
If you want to get virtuals serialized to json object, try doc.toObject({ virtuals: true }) as documented here http://mongoosejs.com/docs/api.html#document_Document-toObject.

Mongoose populate not populating

I am trying to populate my users car inventory. All the cars have a userId attached to them when they are created but when I go to populate the inventory it doesn't work and I get no errors.
Here are my models:
User.js
let UserSchema = mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
inventory: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Car' }]
});
let User = mongoose.model('User', UserSchema);
models.User = User;
Cars.js
let CarSchema = mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
make: {
type: String,
required: true
},
model: {
type: String,
required: true
},
year: {
type: String
}
});
let Car = mongoose.model('Car', CarSchema);
models.Car = Car;
Here is the populate code:
router.route('/users/:user/inventory').get((req, res) => {
User.findById(userId)
.populate('inventory')
.exec((err, user) => {
if (err) {
console.log("ERRROORRR " + err)
return res.send(err);
}
console.log('Populate ' + user)
res.status(200).json({message: 'Returned User', data: user});
});
});
};
This is what a car object looks like in the database:
{
"_id": ObjectId("5759c00d9928cb581b5424d0"),
"make": "dasda",
"model": "dafsd",
"year": "asdfa",
"userId": ObjectId("575848d8d11e03f611b812cf"),
"__v": 0
}
Any advice would be great! Thanks!
Populate in Mongoose currently only works with _id's, though there's a long-standing issue to change this. You'll need to make sure your Car model has an _id field and that the inventory field in User is an array of these _id's.
let CarSchema = new mongoose.Schema(); //implicit _id field - created by mongo
// Car { _id: 'somerandomstring' }
let UserSchema = new mongoose.Schema({
inventory: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Car'
}]
});
// User { inventory: ['somerandomstring'] }
User.populate('inventory')

Categories