i want to populate mongoose schema - javascript

I want to get Products details when user order their item so I saved in Order schema where I passed ref of my product schema in productId
here is my Schema :
const Schema = mongoose.Schema
const OrderSchema=new Schema({
productId:[{_id:{type:Schema.Types.ObjectId,ref:'products'},quantity:{type:Number}}],
status:{type:Number,required:true},
deliverDate:{type:String},
totalAmount:{type:Number,default:0},
userId:{type:Schema.Types.ObjectId,ref:'userDetail'},
Address:{type:Object,required:true},
totalquantity:{type:Number,default:0},
name:{type:String},
method:{type:String,required:true},
txnId:{type:String},
pushToken:{type:String},
coordinates: {
type: [Number, Number],
index: '2d'
},
},{timestamps: true})
module.exports=mongoose.model('orders',OrderSchema)
I want to fetch an Order which populates productId with all products details:
Order.findById(id)
.then(order=>{
res.json({
orders:order
})
}).catch(err=>{console.log(err);next("Network error")})
How can I populate productId?

Related

Using Mongoose Virtual to calculate the sum of values from subdocuments

I am designing a character sheet app for a tabletop RPG.
I have a character schema and an item schema created using Mongoose.
The character schema has a property called equippedItems which is an array of item subdocuments that represent what the character currently has equipped.
I want to add a virtual to the character schema called 'currentLoad' that gets the 'load' value from each item in equippedItems and adds them together to get the total weight of the character's currently equipped items.
How would I go about using mongoose's .virtual() to accomplish this?
Character Schema:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const characterSchema = new Schema({
... //lots of other fields
equippedItems: [
{
type: Schema.Types.ObjectId,
ref: 'Item'
}
],
});
characterSchema.virtual('currentLoad')
//code to get load values from equippedItems, add together, then set the total to currentLoad
.get()
.set()
const Character = mongoose.model('Character', characterSchema);
module.exports = Character;
Item Schema:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const itemSchema = new Schema({
name: {
type: String,
required: true,
trim: true
},
load: {
type: Number,
required: true,
min: 0,
max: 3
},
});
const Item = mongoose.model('Item', itemSchema);
module.exports = Item;

Problem while populating orders and an array of products

I'm trying to create an e commerce web site using react, node and mongodb.
I created the order schema which comports the cmdRef(string), theClient(Id of the user) and an array of Products(with ProductId and qty) like the code below:
Orderchema=new mongoose.Schema({
CmdRef:String,
Client:{type: mongoose.Schema.Types.ObjectId,
ref: 'User'},
TotalProducts:[{ProductId:{type: mongoose.Schema.Types.ObjectId,
ref: 'Product'},Quantity:Number}],
and now I'm trying to create the route to get all the Orders
CommandRouter.get('/AllCommands',async(req,res)=>{
try {
const cmd= await Command.find({}).populate({path: 'Client', select: 'firstName lastName'}).populate({path:'TotalProducts'})
//
res.json(cmd)
} catch(error)
{
return res.status(500).send({message : "error get orders"})
}
})
Here I found a problem while populating the products Id in the table
it populates the client Id and returns all information about the User but fail with the product table this is the full response using PostMan
Have any of you any Idea about how to populate the productId in the TotalProducts table?
Total products is not an ObjectId. You should be populating ProductId instead.
This should work.
const cmd = await Command
.find({})
.populate([
{
path: 'Client',
select: 'firstName lastName'
},
{
path: 'TotalProducts'
populate: 'ProductId'
}
]);

How do i reference 1 Mongoose Schema inside another as its property?

I am trying to make a store app and have created two mongoose schemas. Order.js and Product.js, I want to reference the product schema as a property of the order schema.
Order.js
const mongoose = require('mongoose');
const Product=require('../models/product.js');
const orderSchema = new mongoose.Schema(
{
date: {
type:Date,
default: Date.now},
customerName: String,
customerAddress: String,
creditCard: Number,
products:[] //product model
},
{ timestamps: true }
);
product.js
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema(
{
name: String,
price: Number,
category: String
},
{ timestamps: true }
);
const Product = mongoose.model('Product', productSchema);
module.exports= Product;
This is my approach when it comes to nested schemas in mongoose :
first you have to create an object of your Product schema , to avoid duplicating your Product model , you can create an object :
product
with your fields , then create your Product schema by simply const Product = new Schema(product); , then you can import the product object here in your order.js and declare your schema as follows :
import product;
const Order = new Schema({
......
......
order : {
type : product ,
......
}
})

Mongoose: Count array elements

I have the following Schema with a array of ObjectIds:
const userSchema = new Schema({
...
article: [{
type: mongoose.Schema.Types.ObjectId,
}],
...
},
I will count the array elements in the example above the result should be 10.
I have tried the following but this doesn't worked for me. The req.query.id is the _id from the user and will filter the specific user with the matching article array.
const userData = User.aggregate(
[
{
$match: {_id: id}
},
{
$project: {article: {$size: '$article'}}
},
]
)
console.log(res.json(userData));
The console.log(article.length) give me currently 0. How can I do this? Is the aggregate function the right choice or is a other way better to count elements of a array?
Not sure why to use aggregate when array of ids is already with user object.
Define articles field as reference:
const {Schema} = mongoose.Schema;
const {Types} = Schema;
const userSchema = new Schema({
...
article: {
type: [Types.ObjectId],
ref: 'Article',
index: true,
},
...
});
// add virtual if You want
userSchema.virtual('articleCount').get(function () {
return this.article.length;
});
and get them using populate:
const user = await User.findById(req.query.id).populate('articles');
console.log(user.article.length);
or simply have array of ids:
const user = await User.findById(req.query.id);
console.log(user.article.length);
make use of virtual field:
const user = await User.findById(req.query.id);
console.log(user.articleCount);
P.S. I use aggregate when I need to do complex post filter logic which in fact is aggregation. Think about it like You have resultset, but You want process resultset on db side to have more specific information which would be ineffective if You would do queries to db inside loop. Like if I need to get users which added specific article by specific day and partition them by hour.

Mongoose schema

I have these mongoose schemas:
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
});
var cartSchema= new Schema({
"items": [ItemSchema]
});
but when I want to push a new item in items, mongoose add an _id field(on the new item) but I don't understand why.
if you want to add item without _id field then you should add { _id: false } in ItemSchema.
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
}, { _id: false });
Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.
You can only use this option on sub-documents. Mongoose can't save a document without knowing its id, so you will get an error if you try to save a document without an _id.
Link: http://mongoosejs.com/docs/guide.html#_id

Categories

Resources