How can I grab the ID inside a nested array/objects? - javascript

How can I grab the _id of sellerId inside the products? So my backend crash because I change the schema and won't compute the total sum, so right now, how can I grab it.
so this is my data.
{
"_id": "636656163b470e00d0c44872",
"userId": {
"_id": "6366559f3b470e00d0c447e9",
"studentId": "1234567890"
},
"products": [
{
"productId": {
"_id": "636655f03b470e00d0c447fb",
"title": "Shoe Cabinet",
"img": "https://firebasestorage.googleapis.com/v0/b/tua-ecom.appspot.com/o/1667651055293%5Bobject%20File%5D?alt=media&token=608c62f4-915c-47ce-a817-b025bebff06f"
},
"quantity": 1,
"sellerId": {
"_id": "636655c53b470e00d0c447eb",
"studentId": "1234567891"
},
"_id": "636656163b470e00d0c44873"
}
],
"amount": 100,
"location": "gym",
"time": "8 am",
"status": "pending",
"tax": 1,
"createdAt": "2022-11-05T12:24:54.934Z",
"updatedAt": "2022-11-05T12:24:54.934Z",
"__v": 0
},
This is request.
router.get("/total/:id", async (req, res) => {
const { id } = req.params;
try {
const income = await Order.aggregate([
{$match:
{
"products.sellerId" : {"$elemMatch": {"_id": id}}
}
},
{$project: {amount: 1}},
])
console.log("Hello")
res.status(200).json(income);
} catch (err) {
res.status(500).json({err: err.message});
}
});
note, the id inside the sellerId, is the params I'm using in the router, what I'm trying to do is grab the orders of specific users and compute it.
EDIT: ADDED SCHEMA
OrderSchema.js
const OrderSchema = new mongoose.Schema({
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
products: [
{
productId:{
type: mongoose.Schema.Types.ObjectId, ref: 'Product'
},
quantity: {
type: Number,
default: 1,
},
sellerId: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'
}
}
],
amount: {type: Number,required: true},
location:{type: Object, required:true},
time: {type: String, required: true},
status: {type:String, default: "pending"},
tax: {type: Number,}
}, {timestamps: true}
)
export default mongoose.model('Order', OrderSchema)

Related

How to access nested elements of json object in node js and mongodb

const mongoose = require("mongoose");
const productSchema = mongoose.Schema({
product_name: {
type: String,
required: [true, "Must Enter Product Name"],
},
product_brand: {
type: String,
},
category: {
type: String,
required: [true, "Must Enter Product Catagorey"],
},
reviews: [
{
name: {
type: String,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
comment: {
type: String,
required: true,
},
rating: {
type: Number,
// required: true,
},
},
{ timestamps: true },
],
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
});
module.exports = mongoose.model("Product", productSchema);
Here I want to access the values of commet for Appling filters
Here is is the output of my products
[
{
"_id": "63c4ee520ca7722674d007d5",
"product_name": "Headphones",
"product_description": "xvy",
"product_price": 8000,
"product_brand": "Apple",
"product_color": "White",
"product_stoke": 3,
"category": "Headphones",
"product_image": "public\\images\\uploaded\\products\\167385045002297820433-5f2f-43d1-972a-4b33785393ee.0ad829318c5599f429d2a6e625f8bde3.jpeg",
"product_sku": "#1",
"owner": "63c4ed720ca7722674d007ab",
"reviews": [
{
"name": "Daniyal Alam",
"user": "63c43d54cf582066929c8c46",
"comment": "Good Mobbile Phone",
"rating": 4,
"_id": "63cbce2cd52bf9ecfdf29323"
}
],
"__v": 1
},
{
"_id": "63c4e3530ca7722674d006b6",
"product_name": "Air bud Two.",
"product_description": "In the busy world which is fil.",
"product_price": 50000,
"product_brand": "Apple",
"product_color": "White",
"product_stoke": 5,
"category": "Headphones",
"product_image": "public\\images\\uploaded\\products\\167384763581197820433-5f2f-43d1-972a-4b33785393ee.0ad829318c5599f429d2a6e625f8bde3.jpeg",
"product_sku": "33",
"owner": "63c4d8ac0ca7722674d00529",
"reviews": [],
"__v": 0
},
]
I want to access my comments I tried the following code but it only returns reviews
exports.commentProduct = async (req, res, next) => {
const newproduct = await Product.find({});
try {
const reviews = newproduct?.map((p) => {
if (typeof p.reviews != "undefined") {
console.log(p.reviews);
}
});
const com = reviews?.map((c) => {
// console.log(comments);
});
// const comments = reviews.comment;
return res.status(200).json({
success: true,
reviews,
});
} catch (error) {
return res.status(500).json({
success: false,
message: error.message,
});
}
};
the Console Prints products having reviews but after applying dot notation on reviews I got undefined
[
{
name: 'Daniyal Alam',
user: new ObjectId("63c43d54cf582066929c8c46"),
comment: 'BEst One',
rating: 5,
_id: new ObjectId("63cbce44d52bf9ecfdf29743")
}
]
[]
[]
[]
[]
[]
[]
[]
[]
[
{
name: 'Daniyal Alam',
user: new ObjectId("63c43d54cf582066929c8c46"),
comment: 'pp',
rating: 4,
_id: new ObjectId("63c4f76e0ca7722674d040ae")
}
]
[]
[
{
name: 'Daniyal Alam',
user: new ObjectId("63c43d54cf582066929c8c46"),
comment: 'Good Mobbile Phone',
rating: 4,
_id: new ObjectId("63cbce2cd52bf9ecfdf29323")
}
]
Working with your example, you can map each item, then map the reviews, and get the comment out of each like using the following code
const data = [{
"_id": "63c4ee520ca7722674d007d5",
"product_name": "Headphones",
"product_description": "xvy",
"product_price": 8000,
"product_brand": "Apple",
"product_color": "White",
"product_stoke": 3,
"category": "Headphones",
"product_image": "public\\images\\uploaded\\products\\167385045002297820433-5f2f-43d1-972a-4b33785393ee.0ad829318c5599f429d2a6e625f8bde3.jpeg",
"product_sku": "#1",
"owner": "63c4ed720ca7722674d007ab",
"reviews": [{
"name": "Daniyal Alam",
"user": "63c43d54cf582066929c8c46",
"comment": "Good Mobbile Phone",
"rating": 4,
"_id": "63cbce2cd52bf9ecfdf29323"
}],
"__v": 1
}]
data.map((dat) => {
dat["reviews"].map((rev) => {
document.querySelector('div').innerHTML +=rev["comment"]
})
})
<div></div>

How to create an array entry with ObjectId and Number

I am new to mongodb and am trying to make this type of entry:
{
"resources": [
{
"amount": 1,
"resource": {
"_id": "61be82b9549b4ede0c8df07e"
}
}
]
}
Here is my schema code:
const schema = new Schema({
resources: [
{
amount: {
type: Number,
required: true,
},
resource: {
_id: {
type: Schema.Types.ObjectId,
ref: "Resource"
}
}
}
]
});
here is the json code i send
{
"resources": [
{
"amount": 1,
"resource": {
"_id": "61be82b9549b4ede0c8df07e"
}
}
]
}
After processing the request, the following entry is created
{
"resources": [
{
"amount": 1,
"resource": {
"_id": "61be82b9549b4ede0c8df07e"
},
"_id": "61ebf5d2e47442bd566fe157"
}
],
"_id": "61ebf5d2e47442bd566fe156",
"__v": 0
}
Id for the resource was created correctly, but I can't figure out where the resources._id key came from? Where did I make a mistake?
You have to off _id from schema declaration in the array, after updating schema try inserting new document,
const schema = new Schema({
resources: [
{
_id: false,
amount: {
type: Number,
required: true,
},
resource: {
_id: {
type: Schema.Types.ObjectId,
ref: "Resource"
}
}
}
]
});

Mongodb : Adding new data object into an array of object with node.js mongoose [duplicate]

This question already has answers here:
Mongodb $push in nested array
(4 answers)
Closed 1 year ago.
I want to add a new data object inside of a nested document in MongoDB. this is what my schema look like :
const transactionSchema = new Schema({
transactionType: {type: String, require: true, trim: true},
senderWallet: {type: String, require: true, trim: true},
recipientWallet: {type: String, require: true, trim: true},
amount: {type: Number, require: true, trim: true},
createdAt: {type: Date, require: true},
});
const walletHoldShema = new Schema({
balance: {type: Number},
transaction:[transactionSchema]
});
const walletSchema = new Schema({
createdAt: {type: Date, require: true},
userId: {type: String, require: true, trim: true},
walletAdrress: {type: String},
usdWallet: [walletHoldShema],
})
const Wallets = mongoose.model('wallet', walletSchema);
module.exports = Wallets
This is what my data look like right now
wallet: {
"_id": "60ca5e8e2c57463733b65f89",
"usdWallet": [
{
"_id": "60ca5ede2c57463733b65f8a",
"balance": 0,
"transaction": []
}
],
"createdAt": "2021-06-16T20:28:14.589Z",
"userId": "fb0df5c9a9eb",
"walletAdrress": "fb0df5c9a9eb",
"__v": 0
}
I have tried different solution like this one which I followed via stack :
const _id = req.params._id;
const transactionInput = {
transactionType: 'input',
senderWallet: req.body.sender,
recipientWallet: req.body.recipient,
amount: req.body.amount,
createdAt: Date.now(),
};
walletSchema.findOneAndUpdate({_id: _id}, {$push: {transaction: transactionInput}}, { new: true }, function(err, data){
if (err) {
res.send(err);
} else {
res.send(transactionInput);
}
});
// calling router
router.patch('/v1/sendUSD/', wallet.sendDollar
But I am getting this in my DB after my router is called :
"wallet": [
{
"_id": "60ca5e8e2c57463733b65f89",
"usdWallet": [
{
"_id": "60ca5ede2c57463733b65f8a",
"balance": 0,
"transaction": []
}
],
"createdAt": "2021-06-16T20:28:14.589Z",
"userId": "fb0df5c9a9eb",
"walletAdrress": "fb0df5c9a9eb",
"__v": 0
},
{
"_id": "60ca5e8e2c5746373",
"usdWallet": [
{
"_id": "60ca5ede2c57463733b65f8a",
"transaction":
[
{
"transactionType": "input",
"senderWallet": "fcdhjgknsdfihber",
"recipientWallet": "mbindu",
"amount": "50.0",
"createdAt": 1623881009306
}
]
}
],
},
]
But what I want is this :
wallet: [
{
"_id": "60ca5e8e2c57463733b65f89",
"usdWallet": [
{
"_id": "60ca5ede2c57463733b65f8a",
"balance": 0,
"transaction":
[
{
"transactionType": "in",
"senderWallet": "fcdhjgknsdfihber",
"recipientWallet": "mbindu",
"amount": "50.0",
"createdAt": 1623881009306
},
{
"transactionType": "out",
"senderWallet": "fcdhjgknsdfihber",
"recipientWallet": "mbindu",
"amount": "50.0",
"createdAt": 1623881009306
},
]
}
],
"createdAt": "2021-06-16T20:28:14.589Z",
"userId": "fb0df5c9a9eb",
"walletAdrress": "fb0df5c9a9eb",
"__v": 0
},
]
having an array inside an array is always a bad idea. that said, you can push transaction into usdWallet through:
walletSchema.findOneAndUpdate({ _id: _id }, { $push: { "usdWallet.$.transaction": transactionInput }}, { new: true }, function(err, data) {
if (err) {
res.send(err);
} else {
res.send(transactionInput);
}
});

Trouble using mongoose 'Populate'

Good Morning,
So I seem to have an issue with populating my fields with Node.js and Mongoose. It is just turning up a blank array:
Result: (JSON)
[
{
"courseassignments": [],
"_id": "5db56ceb4cc2c92824ae2651",
"name": "Garibaldi",
"website": "www.garibaldi.org.uk",
"__v": 0
},
{
"courseassignments": [],
"_id": "5db56d074cc2c92824ae2652",
"name": "Kirk Hallam",
"website": "www.kirkhallamacademy.co.uk",
"__v": 0
}
]
Below is the code I am using the call the populate function, plus the models that I am using for each of the data. It is very weird.
*school.js (Model) *
// Require modules within our file:
const mongoose = require('mongoose')
const schoolSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
trim: true
},
website: {
type: String,
required: true,
trim: true
},
logo: {
type: Buffer
},
courseassignments: [{
type: mongoose.Schema.Types.ObjectID,
ref: 'CourseAssignment'
}]
})
// Export the user to use within other files:
const school = mongoose.model('School', schoolSchema)
module.exports = school
courseassignment.js (Model)
// Require modules within our file:
const mongoose = require('mongoose')
const courseAssignmentSchema = new mongoose.Schema({
school: {
type: mongoose.Schema.Types.ObjectID,
required: true,
ref: 'School'
},
course: {
type: mongoose.Schema.Types.ObjectID,
required: true,
ref: 'Course'
}
})
// Export the user to use within other files:
const courseAssignment = mongoose.model('CourseAssignment', courseAssignmentSchema)
module.exports = courseAssignment
* Code to fetch data: (within app.js)*
router.get('/school', async (req, res) => {
const schools = await School.find({}).populate({ path: 'courseassignments' })
res.send(schools)
})
I would remove the courseassigment ref from the School model, and would take advantage of virtual populate.
So here are the steps:
school.js (school model - as you see I removed courseassignments ref, and added options for virtual features)
const mongoose = require('mongoose')
const schoolSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
trim: true
},
website: {
type: String,
required: true,
trim: true
},
logo: {
type: Buffer
}
}, {
toJSON: { virtuals: true },
toObject: { virtuals: true }
})
schoolSchema.virtual("courseassignments", {
ref: "CourseAssignment",
foreignField: "school",
localField: "_id"
})
const school = mongoose.model('School', schoolSchema)
module.exports = school
At this point when you hit the schools endpoint, your response will be like this.
( I only show one item to be short.)
[
{
"_id": "5db5a809cfc9951770d5078a",
"name": "school 1",
"website": "school 1 website",
"__v": 0,
"courseassignments": [
{
"_id": "5db5a892cfc9951770d50790",
"school": "5db5a809cfc9951770d5078a",
"course": "5db5a847cfc9951770d5078d",
"__v": 0
},
{
"_id": "5db5a89ccfc9951770d50791",
"school": "5db5a809cfc9951770d5078a",
"course": "5db5a851cfc9951770d5078e",
"__v": 0
},
{
"_id": "5db5a8a1cfc9951770d50792",
"school": "5db5a809cfc9951770d5078a",
"course": "5db5a858cfc9951770d5078f",
"__v": 0
}
],
"id": "5db5a809cfc9951770d5078a"
},
...
...
]
And if you also want to access to the Course name (which I think would be good),
courseassigment.js
const mongoose = require('mongoose')
const courseAssignmentSchema = new mongoose.Schema({
school: {
type: mongoose.Schema.Types.ObjectID,
required: true,
ref: 'School'
},
course: {
type: mongoose.Schema.Types.ObjectID,
required: true,
ref: 'Course'
}
}, {
toJSON: { virtuals: true },
toObject: { virtuals: true }
})
courseAssignmentSchema.pre(/^find/, function (next) {
this.populate({
path: 'course'
});
next();
});
// an index may be required like this
//courseAssignmentSchema.index({ school: 1, course: 1 }, { unique: true });
const courseAssignment = mongoose.model('CourseAssignment', courseAssignmentSchema)
module.exports = courseAssignment
And with this the result will contain the course related fields like course name.
[[
{
"_id": "5db5a809cfc9951770d5078a",
"name": "school 1",
"website": "school 1 website",
"__v": 0,
"courseassignments": [
{
"_id": "5db5a892cfc9951770d50790",
"school": "5db5a809cfc9951770d5078a",
"course": {
"_id": "5db5a847cfc9951770d5078d",
"name": "course 1",
"__v": 0
},
"__v": 0,
"id": "5db5a892cfc9951770d50790"
},
{
"_id": "5db5a89ccfc9951770d50791",
"school": "5db5a809cfc9951770d5078a",
"course": {
"_id": "5db5a851cfc9951770d5078e",
"name": "course 2",
"__v": 0
},
"__v": 0,
"id": "5db5a89ccfc9951770d50791"
},
{
"_id": "5db5a8a1cfc9951770d50792",
"school": "5db5a809cfc9951770d5078a",
"course": {
"_id": "5db5a858cfc9951770d5078f",
"name": "course 3",
"__v": 0
},
"__v": 0,
"id": "5db5a8a1cfc9951770d50792"
}
],
"id": "5db5a809cfc9951770d5078a"
},
...
...
]
Docs:
https://mongoosejs.com/docs/tutorials/virtuals.html
https://mongoosejs.com/docs/populate.html#populate-virtuals

Nodejs Mongoose Add extra data to model

here is the product model:
const productSchema= new schema({
_id: {
type: String,
default: () => {return uniqid().toUpperCase()}
},
name: {
type: String
},
price: {
type: Number
},
type: {
type: String
},
category: {
type: String
},
sub_category: {
type: String
},
images: {
type: Array
},
sizes: {
type: Array,
default: ['OS']
},
materials: {
type: Array
},
description: {
type: String
},
weight: {
type: String,
default: ''
}
});
and here is the orders model:
let orderSchema = new schema({
products: [productModel],
});
in the product model, there is no quantity entry, but I need to pass the quantity of each product that is sent to the orders Api without changing product model.
example of api call:
{
"products": [{
"images": [
"1",
"2",
"3"
],
"sizes": [
"OS"
],
"materials": [
"Cotton"
],
"weight": "",
"_id": "3EC65ISJWW6LU8C",
"name": "Tshirt",
"price": 10.99,
"type": "Clothing",
"category": "Men Tshirts",
"description": "A Tshirt",
"quantity": 5
},{
"images": [
"upload_7eb7af15fdaf27bff7667ee35ae4a8b0.png",
"upload_7dea46a64b046f2d71a75612aaba1523.png",
"upload_13422483a3b7406620b8e16c0d0ed7df.png"
],
"sizes": [
"OS",
"Os2"
],
"materials": [
"Cotton",
"M2"
],
"weight": "",
"_id": "3EC65ISJWW6LVLM",
"name": "T-Shirt",
"price": 10.99,
"type": "Clothing",
"category": "Men Tshirts",
"description": "A Tshirt",
"quantity": 5
}]
}
So I added the quantity entry but it's not in the product model.
here is how I did it but it's not working:
products: [productModel, {quantity: Number}],
You can use mongoose discriminators for this to extend the base schema
Go through this doc for further details
https://mongoosejs.com/docs/api.html#model_Model.discriminator
Here is a sample example as described in the doc
function BaseSchema() {
Schema.apply(this, arguments);
this.add({
name: String,
createdAt: Date
});
}
util.inherits(BaseSchema, Schema);
var PersonSchema = new BaseSchema();
var BossSchema = new BaseSchema({ department: String });
var Person = mongoose.model('Person', PersonSchema);
var Boss = Person.discriminator('Boss', BossSchema);
new Boss().__t; // "Boss". `__t` is the default `discriminatorKey`
var employeeSchema = new Schema({ boss: ObjectId });
var Employee = Person.discriminator('Employee', employeeSchema, 'staff');
new Employee().__t; // "staff" because of 3rd argument above

Categories