Nodejs - How to populate a subdocument in a Mongoose schema? - node.js

I am creating a basic schema document to read data that should mirror the following document structure:
Document1:
Customer: {
_id: "61fa6cb1a0f4d684063aa66e"
"customerName": "Sam Dobson",
"email": "same#example.com",
"Orders": [
{
"id": "620146f0cbafd7ba64c09daa",
"orderDate": 2022-03-02T14:29:41.523Z,
"image": {
"id": "620146d770ee1e897f245230",
"name": "Cola",
"thumbnail": "cola.jpeg",
"type": "image"
},
"video": null,
"qty": 1
},
{
"id": "620a89b7cbafd7ba64c28930",
"orderDate": 2022-03-07T11:915:12.125Z,
"image": {
"id": "620a8aa170ee1e897f2458fe",
"name": "Pizza",
"thumbnail": "pizza.jpeg",
"type": "image"
},
"video": {
"id": "620a8aa170ee1e897f2458fe",
"name": "PizzaVideo",
"thumbnail": "pizzaVideo.mp4",
"type": "video"
},
qty: 2
}
]
}
Data already exist in a MongoDB instance and I've to read this data for further processing. So far, I've created the following schema:
Customer.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const FileSchema = Schema({
name:{type: String},
thumbnail: {type: String},
type: {type: String}
});
const OrderSchema = Schema({
orderDate: {type: Date},
image:{ type: FileSchema},
video:{type: FileSchema},
qty: {type: Number}
});
const CustomerSchema = Schema({
customerName: {type: String},
email: {type: String},
Orders: [OrderSchema],
});
module.exports = mongoose.model('Customer', CustomerSchema);
Code:
In order to populate data, I'm reading it using Model.find() query.
const findCustomers = async () => {
try{
const customer = await Customer.find().exec();
return customer;
}
catch(err){
return 'error occurred!';
}
}
However, when I run the program it shows the subdocument as:
Customer:{
_id: new ObjectId("62c59c55d8f8fc1b77777b39"),
customerName:"Sam Dobson",
email:"same#example.com",
Orders:[[Object], [Object]]
}
My questions are:
Does the schema correctly reflects the document structure?
What do I need to change in my query to read data from Customer document to populate the order object?

Related

how can I return a subset of a mongo populate call?

I am using the mongo db 'ref' functionality to populate objects from a table into a document that I am returning
Here is the table that stores the object ID ref
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const StaticAssignmentSchema = new Schema({
affiliation: { type: String },
REF_person: [{ type: Schema.Types.ObjectId, ref: 'users' }],
});
module.exports = StaticAssignmentNew = mongoose.model('staticassignments', StaticAssignmentSchema);
Here is my users table schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: { type: String },
phone: { type: String },
password: { type: String },
affiliation: { type: String },
timezone: { type: String },
date: { type: Date, default: Date.now },
});
module.exports = User = mongoose.model('users', UserSchema);
Here is how I am getting the data from mongo
var query = { affiliation: affiliation };
var ret = await StaticAssignment.findOne(query).populate('REF_person');
which returns the following:
{
"_id": "61a8376154377e5704ae79cf",
"affiliation": "800_800",
"REF_person": [{
"_id": "5e441bd5332359211c0403fb",
"name": "Frank",
"phone": "8008008001",
"password": "$2a$10$T9wYLE3v/n8S4GB.oyYOmCsGUdxXQiOjpiDaG0JGbKy",
"affiliation": "800_800",
"timezone": "America/Los_Angeles",
"date": "2020-02-12T15:37:57.167Z"
}]
}
however, I would like to return a subset of the populate call:
{
"_id": "61a8376154377e5704ae79cf",
"affiliation": "800_800",
"REF_person": [{
"_id": "5e441bd5332359211c0403fb",
"name": "Frank",
"phone": "8008008001",
}]
}
what can I do to return the subset ?
thank you Mastermind !
ANSWER:
var query = { affiliation: affiliation };
var ret = await StaticAssignment.findOne(query)
.populate({path: 'REF_person', select: '_id name phone'});
Try var ret = await StaticAssignment.findOne(query).populate({path: 'REF_person', select: 'name phone'});
Check out this page: https://www.codegrepper.com/code-examples/whatever/mongoose+populate+select+fields

MongoDB - Saving sub category details

I would like to know how can I save my product details(sub category) inside an order details.
As for now, MongoDB only saves the ID of the product, without its details.
Order Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Product = require('../models/Product').schema
let Order = new Schema ({
_id: mongoose.Schema.Types.ObjectId,
firstName: {type: String},
lastName: {type: String},
email: {type: String},
phone: {type: Number},
address: {type: String},
product: [{type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true}],
createdAt: {type: Date, default: Date.now}
},
{
collection: 'orders'
}
);
module.exports = mongoose.model('Order', Order);
Product Schema:
// define the table structure for mongoDB
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let Product = new Schema(
{
_id:{
type: mongoose.Schema.Types.ObjectId
},
product_Name:{
type: String
},
product_Description:{
type: String
},
product_Price:{
type: Number
},
product_Img:{
type: String
},
product_Quantity: {
type:Number
},
id:{
type: Number
},
}, {
collection: 'products'
}
);
module.exports = mongoose.model('Product', Product);
Order routing (only post):
//create order
orderRoute.route('/').post((req, res) =>{
Product.findById(req.body.productId)
// .select('product')
.populate('product')
.then(product => {
if(!product){
return res.status(404).json({
message: "product not found"
});
}
const order = new OrderDetails({
_id: new mongoose.Types.ObjectId(),
product:req.body.productId,
email: req.body.email,
firstName:req.body.firstName,
lastName: req.body.lastName,
phone: req.body.phone,
address: req.body.address,
});
return order.save()
})
.then(result => {
console.log(result);
return res.status(200).json({
message: "Order was Created",
order:result,
request:{
type:"GET",
order_url: "http://localhost:5000/order/" + result._id
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error:err.message
});
});
});
MongoDB doc:
**GET method returns fully detailed order(from POSTMAN):
{
"message": "Order was fetched",
"order": {
"product": [
{
"_id": "5e1c9fc052b6b1b6b8fee292",
"product_Name": "Soccer Ball",
"product_Description": "Soccer Ball",
"product_Price": 20,
"product_Img": "./assets/accessories/soccerball.jpg",
"id": 0,
"product_Quantity": 1,
"type": "accessories"
},
{
"_id": "5e5a6309d07a33280ce8c49d",
"product_Name": "Air Pegasus 36",
"product_Description": "Shoes 3",
"product_Price": 80,
"product_Img": "./assets/shoes/nike-mens air-zoom-pegasus-36-running-shoes.JPG",
"id": 14,
"product_Quantity": 1,
"type": "shoes"
}
],
"_id": "5eadacbf1260955398655ff7",
"email": "tal",
"firstName": "hhhhh",
"lastName": "hhhh",
"phone": 123,
"address": "tal",
"createdAt": "2020-05-02T17:24:15.419Z",
"__v": 0
},
"request": {
"type": "GET",
"all_orders_url": "http://localhost:5000/order"
}
Much Appreciated!
you can do that by embeding documents.
https://docs.mongodb.com/manual/core/data-modeling-introduction/
this approach is called denormaization and it will cause you data duplication in the product field, which may be needed in your case since the price of the product may change over time, but will make the products harder to manage in case you dropped the products collection.
I suggest that you keep the reference but add any data that might be changing to the order details collection.

What field type we can use in mongo to store an array of objects?

What field type we can use in mongo to store an array of objects?. I wanted to store the data below .I have my implementation below and i have added the code maybe you can check it somehow and let me know where is the part where i got an issue or error. I have also provided the sample data. The issue with the current implementation is it does not save the data the books array in the databse is 0 elements
Sample data
{
"books":
[
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
"edition": 3,
"year": 2011
},
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C.Zakas"
],
"edition": 2,
"year": 2009
}
]
}
#implementation
const schema = new Schema({
books: [{ type: mongoose.Schema.Types.Mixed }]
})
var RouterData = mongoose.model('RouterData', schema);
var routerData = {
"books":
[
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
"edition": 3,
"year": 2011
},
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C.Zakas"
],
"edition": 2,
"year": 2009
}
]
}
var data = new RouterData({routerData: routerData});
data.save();
I think you can define the schema like this.
const booksSchema = new Schema({
books: [{
title: String,
authors: [String],
edition: Number,
year: { type: Date }
}]
})
Define your schema in mongoose like this:
const BookSchema = new mongoose.Schema({
title: String,
authors: [String],
edition: Number,
year: Number,
}, {
_id: false,
});
const MySchema = new mongoose.Schema({
books: [BookSchema],
});
If you are using mongoose then you should do in your schema
books: [{ type: mongoose.Schema.Types.Mixed }]
mixed means that it can take anything object, array etc. you can check https://mongoosejs.com/docs/schematypes.html#mixed
This should work:
const mongoose = require('mongoose');
const BookSchema = new mongoose.Schema({
title: { type: String },
authors: [String],
edition: { type: Number },
year: { type: Number },
});
const MySchema = new mongoose.Schema({
books: [BookSchema],
});
module.exports = mongoose.model('MySchema', MySchema);

Post insert multiple data using express js and mongodb

im trying to insert data in mongodb using express in the format as below which im not able to achieve.
I need to enter multiple product and serial no in the data field. please help!
[
{
"_id": "5cbabbd7545ac20f7c912e6a",
"refno1": "REF1",
"refno2": "REF2",
"prodregdate": "2019-04-09T00:00:00.000Z",
"data": [
{
"_id": "5cbabbd7545ac20f7c912e6b",
"product": "5cb86b45cfafaa1860e29b2a",
"serialno": "s123"
},
{ // this data im not able to enter how to do it
"_id": "5cbabbd7545ac20f7c912e6b",
"product": "5cb86b45cfafaa1860e29b2a",
"serialno": "s123"
},
],
"customer": {
"_id": "5c98bb0a42207b16d8fbd3cf",
"customername": "Raghav Update"
},
"customertype": {
"_id": "5c7a1a1d4913fa08ac75c027",
"customertype": "Government "
},
"__v": 0
}
]
// My Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ProductRegistrationSchema = new Schema({
//Product Details
_id: { type: mongoose.Schema.Types.ObjectId },
refno1: { type: String },
refno2: { type: String },
data: [{
product: {
type: mongoose.Schema.Types.ObjectId,
ref: "product"
},
//DATES
//OEM
oemwarrantyfrom: { type: Date },
oemwarrantyto: { type: Date },
//SERVICE PROVIDER
warrantyfrom: { type: Date },
warrantyto: { type: Date },
serialno: { type: String },
}],
prodregdate: { type: Date },
//Details of Customer buying the product
customer: {
type: mongoose.Schema.Types.ObjectId,
ref: "customer"
},
customertype: {
type: mongoose.Schema.Types.ObjectId,
ref: "customertype"
},
department: {
type: mongoose.Schema.Types.ObjectId,
ref: "customersubdepartment"
},
remarks: { type: String },
entrydate: {
type: Date,
dafault: Date.now
}
module.exports = ProductRegistration = mongoose.model('productregistration', ProductRegistrationSchema);
// My Routes just for add
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Product = require("../../../models/Master/Products");
//importing the model of ProductRegistrationSchema
const ProdReg = require('../../../models/Entries/ProductRegistration');
//Creating a new ProductRegistration Data
router.post('/add', (req, res)=>{
const newProdReg = new ProdReg({
_id: new mongoose.Types.ObjectId(),
refno1: req.body.refno1,
refno2: req.body.refno2,
prodregdate: req.body.prodregdate,
data: {
product: req.body.productid,
oemwarrantyfrom: req.body.oemwarrantyfrom,
oemwarrantyto: req.body.oemwarrantyto,
warrantyfrom: req.body.warrantyfrom,
warrantyto: req.body.warrantyto,
serialno: req.body.serialno,
},
customer: req.body.customerid,
customertype: req.body.customertypeid,
department: req.body.customersubdepartmentid,
remarks: req.body.remarks
// deliverydate: req.body.deliverydate,
// address: req.body.address,
// assignedto: req.body.employeesid,
// warrantyprovider: req.body.serviceproviderid,
// oemwarrantyprovider: req.body.oemcompanyid,
// warrantystartdate: req.body.warrantystartdate,
// warrantyexpiredate: req.body.warrantyexpiredate,
});
newProdReg.save().then(prodreg => res.json(prodreg));
});
im not able to enter 2 product and serial no in the data field. One one is getting entered.
Firstly make your request JSON in the proper format if you want to insert two products which you are getting from request data.
For example, your request JSON should be in the flowing format:
{"refno1":"x", "refno2": "y", "prodregdate": "2019-04-19T18:30:00.000Z","data": [{"product": "product_1_object_id","oemwarrantyfrom":"2019-04-19T18:30:00.000Z", "oemwarrantyto": "2019-04-19T18:30:00.000Z","warrantyfrom":"2019-04-19T18:30:00.000Z", "warrantyto":"2019-04-19T18:30:00.000Z","serialno":"123" },{"product": "product_2_object_id","oemwarrantyfrom":"", "oemwarrantyto": "2019-04-19T18:30:00.000Z","warrantyfrom":"2019-04-19T18:30:00.000Z", "warrantyto":"2019-04-19T18:30:00.000Z","serialno":"456" }],"customersubdepartmentid":"departement_object_id","customerid":"customer_object_id","customertypeid":"customer_type_object_id","remarks":"anything"}
If you are using POSTMAN then you can try this JSON in the "raw" option.
Then in your code, it should be like below:
router.post('/add', (req, res)=>{
const newProdReg = new ProdReg({
_id: new mongoose.Types.ObjectId(),
refno1: req.body.refno1,
refno2: req.body.refno2,
prodregdate: req.body.prodregdate,
data: req.body.data, // This will be type array with two products details
customer: req.body.customerid,
customertype: req.body.customertypeid,
department: req.body.customersubdepartmentid,
remarks: req.body.remarks
});
newProdReg.save().then(prodreg => res.json(prodreg));
});
Please match your request param with JSON I took it from your schema.

saving complex structure in mongodb using express and mongo

I'm new to mongodb, node and express. I I'm trying to save these data in mongodb.
I have staff.model.js as follows
let StaffSchema = new Schema({
staffcode:String,
firstname:String,
lastname: String,
type: String,
department:String,
dateofjoin:Date,
lastworkingday:Date,
teaching:[ {type:Schema.Types.ObjectId, ref:'Teaches'} ]
});
I have another schema named teaches as follows
let TeachesSchema = new Schema({
standard:{type: Schema.Types.ObjectId, ref: 'Standard'},
subjects:[{type: Schema.Types.ObjectId, ref: 'Subject'}]
});
another schema of standards as follows
let StandardSchema = new Schema({
name:String,
medium:String,
section:String
});
another schema subjects as follows
let SubjectSchema = new Schema({
name:{ type: String, required: true, max: 25 }
});
finally I'm trying to save data in mogodb as like
exports.staff_create = function(req, res){
let staff = new Staff({
staffcode:req.body.staffcode,
firstname:req.body.firstname,
lastname: req.body.lastname,
type: req.body.type,
department:req.body.department,
dateofjoin:req.body.dateofjoin,
teaching:req.body.teaching
});
staff.save(function(err){
if(err){
return next(err);
}
res.send('Staff created successfully');
});
};
making api call from postman with input like this
{
"staffcode": "STF0003",
"firstname": "Joh Doe",
"lastname": "Moy",
"type": "teaching",
"department": "physics",
"dateofjoin": "2018-06-01",
"teaching": {
"standard": {
"_id": "5cb8ff551a1c1a2514fa467c",
"name": "1",
"medium": "English",
"section": "A"
},
"subjects": [
{
"_id": "5cb8ed65c068b22f5489d050"
},
{
"_id": "5cb8ed6bc068b22f5489d051"
}
]
}
}
what is wrong in this? I'm not able to get success response in postman request.
your schema design is coming from relational databases. However you can do what you ask by using populate.
a better way would be to use embedded documents instead of referrals in some places check this answer about MongoDB relationships: embed or reference?

Resources