Mongoose get multiple collection data using query - node.js

I am trying to join two mongoose collection and fetch all related details using the query which i have mention below. Problem is I am getting only one table details employee collection not able get two collection detail when I call GetEmployeeDetails(emp_id) . Need a suggestion. How to get two collection data in one query.
const EmployeeInfoSchema = mongoose.Schema({
employee_id: String,
client_id: {
type: Schema.Types.Number,
ref: "client",
},
email: String,
contact: String,
});
const ClientInfoSchema = mongoose.Schema({
client_id: Number,
employee_id: {
type: Schema.Types.String,
ref: "employee",
},
project: String,
organization: String,
});
let employeeInfo = mongoose.model("employee", EmployeeInfoSchema);
let clientInfo = mongoose.model("client", ClientInfoSchema);
module.exports = { employeeInfo, clientInfo };
Query
async function GetEmployeeDetails(emp_id) {
let employee_info = await Storage.employeeInfo
.find()
.where({ employee_id: emp_id })
.populate({
path: "client",
})
.exec(function (err, block) {
if (err) {
console.log("%s", err);
}
console.log("Employee details is %s", employee_info);
});
return employee_info;
}

Try to change your GetEmployeeDetails method like this:
async function GetEmployeeDetails(emp_id) {
try {
let employee_info = await Storage.employeeInfo
.find({ employee_id: emp_id })
.populate('client')
.exec(function (err, block) {
if (err) console.log('%s', err);
else console.log('Employee details is %s', employee_info);
});
return employee_info;
} catch (err) {
res.status(400).send('Error getting details');
}
}

Related

Mongoose Nested Queries - find and updating two fields in different documents

What Im trying to do is have one user send an amount to another user, Id like for the amount to be subtracted from the sender's balance, and added to the receiver's balance. The problem is that the receivers balance is updated and works, but the previous query to subtract the amount from the sender isn't working.
I understand there are no joins in mongoose (at least not in the classical sense), so Id need to query the user's balance first and then update it in another query. But surely there is a way to nest these queries? Im hoping I just have the syntax wrong.
user.js
const { Decimal128 } = require("mongodb");
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
useraddress: {
type: String,
required: true,
},
userbalance: {
type: Decimal128,
required: true,
}
});
module.exports = User = mongoose.model("users", UserSchema);
server.js
app.post("/sendamount", function (req, res) {
var amount = 100;
var senderAddress = "Bob123";
var receiverAddress = req.body.receiver;
// Take amount from sender balance
User.findOne({useraddress:senderAddress}, (err, sub) => {
if (err) return handleError(err);
var mybalance = parseFloat(sub.userbalance)
console.log(mybalance)
User.findOneAndUpdate(
{ useraddress: senderAddress },
{ userbalance: mybalance - amount }),
// send to receiver balance
User.findOne({useraddress:receiverAddress}, (err, sub2) => {
if (err) return handleError(err);
var receiverbalance = parseFloat(sub2.userbalance)
console.log(receiverbalance)
// add amount to receiver's balance
User.findOneAndUpdate(
{ useraddress: receiverAddress },
{ userbalance: receiverbalance + amount },
function (err, data) {
if (err) res.send(err);
res.send(data);
console.log("found " + data)
}
)
})
})
})
Would someone mind checking my code? Thanks
try to this subtrack process
I added example field, you have this areas change
const asyncSubtrackProcess = async (id, amount) => await User.findOneAndUpdate({
_id: mongoose.Types.ObjectId(id),
userbalance: { $gt: 0 }
},
{
$inc: {
userbalance: - parseInt(amount)
}
});
const result = () => amounts.map(async item => await asyncSubtrackProcess(item.id, item.amount));
result();

Node express find and return response multple models

I'm fairly new to node & express, I'm trying to implement a register application.
I have 2 models, both models have one common field 'empID'.
const RegisterEntriesSchema = mongoose.Schema({
empID: Number,
registerType: String,
registerItemsQuantity: Number,
registerItemsDesc: String
}, {
timestamps: true
});
const RegisterEmpSchema = mongoose.Schema({
empID: Number,
empName: String,
empPhone: String,
empProj:String
}, {
timestamps: true
});
For my get call in which I need to merge the values, I get from RegisterEmpSchema with its corresponding
employee details from RegisterEmpSchema.
exports.findAllRegisterEntries = (req, res) => {
registerEntriesModel.find()
.then(result => {
var updatedResponse=[];
console.log(result[0].empID);
for(var i=0;i<result.length;i++){
registerEmpModel.find({ empID: result[i].empID })
.then(result2 => {
**//unable to access result here**
}).catch(err => {
console.log("exception catch called findAllRegisterEntries, find employee details "+err);
});
}
res.send(updatedResponse);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving register."
});
});
};
I basically need to get register data and its corresponding employee data.
How do I modify my find() code to use the key empID and do a join query fetch?
I think you better use populate, add ref to empID inside RegisterEntriesSchema
const RegisterEmpSchema = new mongoose.Schema({
empID: Number,
empName: String,
empPhone: String,
empProj: String
}, {
timestamps: true
});
const registerEmpModel = mongoose.model('RegisterEmpSchema', RegisterEmpSchema, 'registerEmployeeCollection');
const RegisterEntriesSchema = new mongoose.Schema({
registerType: String,
registerItemsQuantity: Number,
registerItemsDesc: String,
empID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'RegisterEmpSchema'
}
}, {
timestamps: true
});
RegisterEntriesSchema.index({ createdAt: 1 }, { expires: '525601m' });
const registerEntriesModel = mongoose.model('RegisterEntriesSchema', RegisterEntriesSchema, 'registerEntriesCollection');
module.exports = {
registerEmpModel, registerEntriesModel,
}
then use populate() to populate the RegisterEntriesSchema with correspondence empID
RegisterEntriesSchema.
find().
populate('empID').
exec(function (err, data) {
if (err) return console.log(err);
res.send(data);
});
check mongoose docs: https://mongoosejs.com/docs/populate.html

Call a related collection via populate

I try to call a related list of logs for a certain user via Mongoose populate. Who can help me with finishing the response?
These are the schemes:
const logSchema = new Schema({
logTitle: String,
createdOn:
{ type: Date, 'default': Date.now },
postedBy: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'}
});
const userSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
logs: { type: mongoose.Schema.Types.ObjectId, ref: 'logs' }
});
mongoose.model('User', userSchema);
mongoose.model('logs', logSchema);
Inspired by the Mongoose documentary (see above) and other questions in relation to this subject I think I got pretty far in making a nice get. request for this user. I miss the expierence to 'translate it' to Express.
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
response = { //question
log: {
user: user.logs
}
};
res
.status(200)
.json(response);
});
} else { }); //
}
};
The response in Postman etc would be something like this:
{
"log": {5a57b2e6f633ce1148350e29: logTitle1,
6a57b2e6f633ce1148350e32: newsPaper44,
51757b2e6f633ce1148350e29: logTitle3
}
First off, logs will not be a list of logs; it will be an object. If you want multiple logs for each user, you will need to store is as an array: logs: [{ type: mongoose.Schema.Types.ObjectId, ref: 'logs' }]
From the Mongoose docs: "Populated paths are no longer set to their original _id , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results." In other words, in your query user.logs will be the logs document for each user. It will contain all the properties, in your case logTitle, createdOn, and postedBy.
Sending user.logs as json from the server is as easy as: res.json(user.logs). So your query can look like this:
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
res.status(200).json(user.logs)
});
} else { }); //
}
};
I hope this makes it a little bit clearer!

Upsert Mongoose Error

I'm pretty new to Mongoose/Mongo and node.js, so I suspect this is just a misunderstanding on my side, I have some problem when I try to upsert my object.
Here What have I try to use upsert in my code :
app.post("/api/orders/:id", async (req, res) => {
const { id, name, email, phone, data, item } = req.body;
const existingVisitor = await Visitor.findOne({ email: email.trim() });
if(existingVisitor){
delete Visitor._id;
}
const OrderSchema = await new Order({
orderDate: new Date(),
item: item
});
const visitor = await new Visitor(
{ email: email.trim() },
{
name: name,
email: email.trim(),
phone: phone,
data: data,
createDate: new Date(),
_user: req.params.id,
order: [OrderSchema]
},
{ upsert: true, setDefaultsOnInsert: true }
);
try {
await visitor.update();
console.log("Sucess!");
} catch (err) {
res.status(422).send(err);
}
When I'm Trying to test it in Postman, I got error result following error : After applying the update to the document {_id: ObjectId('59f1896ccabc4f12bc17e5c6') , ...}, the (immutable) field '_id' was found to have been altered to _id: null
What should I do to fix that error?

Schema declaration and subdocument

Can you tell me what i'm doing wrong ?
var ObjectId = Schema.Types.ObjectId;
var ProductSchema = new Schema({
name: { type: String, required: true },
price: { type: Number, required: true },
category : { type: String, required: true }
});
var OrderSchema = new Schema({
products: [{
product: {type: ObjectId, ref: 'Product'},
quantity: {type: Number}
}],
status: { type: String, required: true }
});
Product = mongoose.model('Product', ProductSchema);
Order = rmongoose.model('Order', OrderSchema);
OrderSchema.statics.addOrder = function (data, cb) {
// data: array of products ID
var newOrder = new Order();
data.data.forEach(function(element, index, array) {
Product.findOne({ '_id': element.id }, function (err, product) {
if (err) return handleError(err);
newOrder.products.push({product: product, quantity: element.quantity});
})
});
newOrder.status = 'waiting';
newOrder.save(function (err, order) {
if (err) cb(err, false);
console.log(order);
var response = json.stringify({
event: 'addOrder',
success: true,
data: order.id
});
cb(false, response);
});
}
When i add an order products, array is always empty but i have no error. Maybe it's the wrong to do what i want.
Data send by the client are good and the foreach and findOne work well but push seems doing nothing.
If there is no solution maybe you can try to help me to find another solution.
Thanks :)
That's because you need to wait for all the products to be found.
Try this (untested):
OrderSchema.statics.addOrder = function (data, cb) {
// data: array of products ID
var newOrder = new Order();
var productIds = [];
var quantity = [];
data.data.forEach(function(element, index, array) {
productIds.push(element.id);
quantity.push(element.quantity);
});
Product.find({ '_id' : { $in: productIds} }, function(err, products) {
if (err) return handleError(err);
products.forEach(function(product, index) {
newOrder.products.push({product: product, quantity: quantity[index]});
});
newOrder.status = 'waiting';
newOrder.save(function (err, order) {
if (err) cb(err, false);
console.log(order);
var response = json.stringify({
event: 'addOrder',
success: true,
data: order.id
});
cb(false, response);
});
});
});

Resources