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"
}
}
])
Related
I have an array of objectIDs references in mongo. I want to get a specific element in that array after populating the objectIDs. the problem is i get an empty array.
Here's my schema
// Patient Schema - start
const patientSchema = new mongoose.Schema({
nom: {
type: String,
required:true
},
prénom: {
type: String,
required:true
},
naissance:{
type:Date,
},
adresse: {
type: String,
required:true
},
téléphone: {
type: String,
required:true
},
profession: {
type: String,
},
/// the field i'm trying to populate
consultations:[{
type: mongoose.Schema.Types.ObjectId,
ref:'Consultation'
}],
salle:{
type: mongoose.Schema.Types.ObjectId,
required: true,
ref:'Salle'
},
date:{
type:String,
default: Date.now
},
jointes: {
type:Array
},
questionnaire: {
type:Object
},
}, { collection : 'patients'} );
const patients = mongoose.model('Patient', patientSchema);
Consultation schema
const consultationSchema = new mongoose.Schema({
date: {
type: String,
required:true
},
motif:{
type: String,
},
observations: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Observation"
}],
paiements: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Paiement"
}],
ordonnances: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Ordonnance"
}]
});
const consultations = mongoose.model('Consultation', consultationSchema);
the exports
module.exports = {
patients: patients,
consultations: consultations,
}
The router where i'm trying to populaet consultation field and then get the item
const {patients} = require('./patient.models')
const {consultations} = require('./patient.models')
// not working , getting empty array
const patient = await patients.find({"consultations.motif" : "Checking"}).populate('consultations')
res.send(patient)
The mongo db record , to show you that the field does exist
Here's what i get when i do make the following query iwthout specifiying the field
const patient = await patients.find().populate('consultations')
res.send(patient)
This question already has been answered here: Find after populate mongoose
Here is the solution for your case which does not involve changing the database structure:
const patient = await patients.find().populate({
path: 'consultations',
match: {
motif: 'Checking'
}
})
res.send(patient)
I have 2 schemas:
const mongoose = require('mongoose');
const PinSchema = new mongoose.Schema({
title: String,
content: String,
image: String,
latitude: Number,
longitude: Number,
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
},
comments: [
{
text: String,
createdAt: {
type: Date,
default: Date.now,
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
}
}
}
]
}, { timestamps: true });
module.exports = mongoose.model("Pin", PinSchema);
and
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: String,
email: String,
picture: String
});
module.exports = mongoose.model("User", UserSchema);
As you can see author field in Pin is the same as the _id in User schema.
I then try to populate the comments author field in the Pin schema like this:
const pinUpdated = await Pin.findOneAndUpdate(
{ _id: pinId },
{ $push: { comments: "some comment" } },
{ new: true }
).populate("author")
.populate("comments.author");
however the result object has author field set to null so population doesn't work.
I'm not against doing this with native mongo syntax using $lookup but in my case it's not just looking up an array it's looking up a field of an objects array:
db.pins.aggregate([
{
$lookup:
{
from: "users",
localField: "comments._id", // this won't work
foreignField: "_id",
as: "authorOutput"
}
}
])
what am I missing in populate()?
It looks like your author field in the comments array is nested inside the createdAt object, which is likely unintentional. Changing PinSchema to the following (closing curly brace before author) should fix it:
const PinSchema = new mongoose.Schema({
...
comments: [
{
text: String,
createdAt: {
type: Date,
default: Date.now,
},
author: {
type: mongoose.Schema.ObjectId,
ref: "User"
}
}
]
}, { timestamps: true });
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.
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.
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')