mongoose mongo.js save array with array to collection - node.js

I have this "schema" in mongoose, an array in my dictionary and have other embedded array,
I can save if no embedded object is present, how to save embedded objects?
var ReportSchema = new Schema({
appVersion: { type: String, required: true},
osVersion: { type: String, required: true},
deviceType: { type: String, required: true},
userID: { type: String, required: true},
sessionIDtimestamp: { type: String, required: true},
eventItem : [new Schema ({
eventType:{type :String},
startTime:{type :String},
endTime:{type :String},
params:[new Schema ({
val:{type :String}
})]
})]
});
on my router:
apiRouter.route('/report')
.post(function(req, res) {
var report = new Report();
report.appVersion = req.body.appVersion;
report.osVersion = req.body.osVersion;
report.deviceType = req.body.deviceType;
report.userID = req.body.userID;
report.sessionIDtimestamp = req.body.sessionIDtimestamp;
for (var i = req.body.events.length - 1; i >= 0; i--) {
var requestStringa = util.inspect(req.body.events, {showHidden: false, depth: null});
console.log("entro :"+requestStringa);
};
report.save(function(err) {
if (err) {
return res.send(err);
}
res.json({ message: 'report created!' });
});
})
also i dont think that way to enumerate the array is nice?
edit
the log of events
entro :[ { eventType: 'Account_Rated_Pressed',
startTime: '1435819399',
endTime: '1435819399',
params: [ { paramKey: 'rating', paramValue: '5' } ] },
{ eventType: 'RateableDetail',
startTime: '1435819399',
endTime: '1435819399',
params: [ { paramKey: 'rating', paramValue: '5' } ] } ]
how to save my embedded objects cheers

For saving embedded documents, just assign the array field eventItem the request object value as follows:
apiRouter.route('/report')
.post(function(req, res) {
var report = new Report();
report.appVersion = req.body.appVersion;
report.osVersion = req.body.osVersion;
report.deviceType = req.body.deviceType;
report.userID = req.body.userID;
report.sessionIDtimestamp = req.body.sessionIDtimestamp;
report.eventItem = req.body.events;
report.save(function(err) {
if (err) {
return res.send(err);
}
res.json({ message: 'report created!' });
});
})
In the instance that req.body.event is an object not an array, you would then need to use the JavaScript push() method to push the object to the array. Say for example, if req.body.event has the structure
{
eventType: 'Account_Rated_Pressed',
startTime: '1435819399',
endTime: '1435819399',
params: [ { paramKey: 'rating', paramValue: '5' } ]
}
you can then do
apiRouter.route('/report')
.post(function(req, res) {
var report = new Report();
report.appVersion = req.body.appVersion;
report.osVersion = req.body.osVersion;
report.deviceType = req.body.deviceType;
report.userID = req.body.userID;
report.sessionIDtimestamp = req.body.sessionIDtimestamp;
report.eventItem.push(req.body.event);
report.save(function(err) {
if (err) {
return res.send(err);
}
res.json({ message: 'report created!' });
});
})

Related

save unique json key value pair in mongoose schema

the question is to save unique value generated from multiple sources into one Schema. This schema is a placeholder for all individual data and there should not be any repeat.
(function() {
ContactUniqueMarketingSchema = module.exports = mongoose.Schema({
contacts: [{
displayName: { type: String },
emails: [Object],
familyName: { type: String },
firstName: { type: String },
id: { type: String },
middleName: { type: String },
phoneNumbers: [Object],
rawId: { type: String },
location: {
type: Object,
properties: {
type: {
type: String,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: {
type: [Number],
default: [0, 0]
}
}
},
created_at: { type: Date, default: Date.now },
}],
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now }
});
ContactUniqueMarketingModel = module.exports = mongoose.model("ContactUniqueMarketingModel", ContactUniqueMarketingSchema);
})()
below is the code as how I am saving it. however I do try to filter the data beforehand but in few edge cases duplicates values do come in. the filter function only filter from the JSON object. however there is no way of knowing from Schema
(function() {
function transformContact(contacts) {
var transformedContact = [];
if (contact) {
contact.forEach(function(tupleContact, index) {
});
}
};
function getUniqueContact(contacts) {
log('Get Unique Contact Value :');
var UniqueContacts = [];
var contactMap = new Map();
contacts.forEach(row => {
if (!contactMap.has(row.phoneNumbers[0].value.toString())) contactMap.set(row.phoneNumbers[0].value.toString(), row);
});
for (var value of contactMap.values()) {
UniqueContacts.push(value);
};
return UniqueContacts;
}
DeviceInformationSchema.pre('findOneAndUpdate', function(next) {
log('DeviceInformationSchema findOneAndUpdate Hook :');
var device = this;
var contactToSave = [];
device.contacts = getUniqueContact(device.contacts);
contactToSave.push(device.contacts);
var contactSaveTuple = new ContactUniqueMarketingModel(contactToSave);
contactSaveTuple.save(function(errSave, saved) {
if (errSave) {
log('Error Occured Saving New Data :');
}
log('Successfully Added Data To ContactUniqueMarketingModel Via Save');
next();
});
});
DeviceInformationSchema.pre('save', function(next) {
log('DeviceInformationSchema Save Hook :');
var device = this;
var contactToSave = [];
device.contacts = getUniqueContact(device.contacts);
contactToSave.push(device.contacts);
var contactSaveTuple = new ContactUniqueMarketingModel(contactToSave);
contactSaveTuple.save(function(errSave, saved) {
if (errSave) {
log('Error Occured Saving New Data :');
}
log('Successfully Added Data To ContactUniqueMarketingModel Via Save');
next();
});
});
DeviceInformationSchema.pre('update', function(next) {
log('DeviceInformationSchema update Hook :');
var device = this;
var contactToSave = [];
device.contacts = getUniqueContact(device.contacts);
contactToSave.push(device.contacts);
var contactSaveTuple = new ContactUniqueMarketingModel(contactToSave);
contactSaveTuple.save(function(errSave, saved) {
if (errSave) {
log('Error Occured Saving New Data :');
}
log('Successfully Added Data To ContactUniqueMarketingModel Via Update');
next();
});
});
// });
})()
Above schema, values are inserted into the common Schema which contains only contacts. The save mechanism is performed from hooks from another Schema
Please suggest

How to Calculate and return a total cart items in Nodejs and Express

I've been going back and forth on this code for sometime now and I'm trying to have a totalQty value in the cart object that returns total number of items in the cart and I want to use that value in the views of course right next to the cart icon in the navigation. Here is my code for the user model and routes:
User model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
role: {
type: String,
default: 'BASIC'
},
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
address: {
type: String
},
apartment: {
type: String
},
country: {
type: String
},
state: {
type: String
},
city: {
type: String
},
zip: {
type: String
},
phone: {
type: String
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
resetToken: String,
resetTokenExpiration: Date,
cart: {
items: [
{
productId: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: { type: Number, required: true }
},
],
totalQty: {
type: Number,
default: 0
}
}
}, { timestamps: true });
userSchema.methods.addToCart = function (product) {
const cartProductIndex = this.cart.items.findIndex(cp => {
return cp.productId.toString() === product._id.toString();
});
let newQuantity = 1;
// let newTotalQty = 1;
const updatedCartItems = [...this.cart.items];
if (cartProductIndex >= 0) {
newQuantity = this.cart.items[cartProductIndex].quantity + 1;
updatedCartItems[cartProductIndex].quantity = newQuantity;
newTotalQty = this.cart.totalQty + 1;
updatedTotalQty = newTotalQty;
} else {
updatedCartItems.push({
productId: product._id,
quantity: newQuantity
});
}
const updatedCart = {
items: updatedCartItems,
totalQty: updatedTotalQty
};
this.cart = updatedCart;
return this.save();
};
userSchema.methods.removeFromCart = function (productId) {
const updatedCartItems = this.cart.items.filter(item => {
return item.productId.toString() !== productId.toString();
});
this.cart.items = updatedCartItems;
return this.save();
};
userSchema.methods.clearCart = function () {
this.cart = { items: [] };
return this.save();
};
module.exports = mongoose.model('User', userSchema);
User routes:
exports.getCart = (req, res, next) => {
// populate req user
req.user
.populate('cart.items.productId')
.execPopulate()
.then(user => {
const products = user.cart.items;
// render cart view
res.render('shop/cart', {
path: '/cart',
pageTitle: 'Cart - Hashing365.com',
products: products
});
})
.catch(err => {
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
});
};
exports.postCart = (req, res, next) => {
// extract prod ID
const prodId = req.body.productId;
// run DB find with prod ID
Product.findById(prodId)
.then(product => {
// return true && add to cart
return req.user.addToCart(product);
})
.then(result => {
// re-render same page
res.redirect('back');
})
.catch(err => {
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
});
};
Would really appreciate if someone could help me with a way to do that. Thanks!
You can look into Array reducer function. It should look like this
cart.totalQty = cart.items.reduce((sum, item)=>{
return sum + item.quantity;
},0);

How do I update nested array values in mongoose?

I am fairly new to nodejs/express and I'm practicing full stack development with devchallenges.io, i'm doing the shoppingify challenge. I'm trying to update the quantity of an item I am targeting inside of the items array. I understand my attempt below was terrible, I'm really struggling to understand the logic to be able to do so.
// #route PUT api/list/item/quantity/:id
// #desc Increase or decrease quantity
// #access Private
router.put('/item/quantity/:id', auth, async (req, res) => {
const { action } = req.body;
try {
let list = await List.findOne({ user: req.user.id });
const item = list.items.find(
(item) => item._id.toString() === req.params.id
);
list = list.updateOne(
{ 'items._id': req.params.id },
{ $set: { 'items.quantity': item.quantity + 1 } }
);
await list.save();
return res.json(list);
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
});
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ListSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
},
name: {
type: String,
default: 'Shopping List',
},
items: [
{
name: {
type: String,
default: '',
},
note: {
type: String,
default: '',
},
image: {
type: String,
default: '',
},
category: {
type: String,
default: '',
},
quantity: {
type: Number,
default: 1,
},
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = List = mongoose.model('list', ListSchema);
Look this is my update-vendor route here I'm updating nested street and city name.
router.put("/update-vendors", async (req, res, next) => {
const vendor = await Vendor.updateOne(
{
"address.street": "Street2",
},
{
$set: {
"address.$.street": req.body.street,
"address.$.city": req.body.city,
},
}
);
res.status(200).json(vendor);
});
You can update particular things with the help of $set and other $push method

Mongoose: how to only populate, sort and return a nested object?

I have a User schema, with a messages array. The message array is filled by conversations id and referenced to a Conversation schema.
I want to fetch all conversations from a user, sort them by unread and then most recent messages. Finally, I must only return an array of lastMessage object.
For the moment, I have only managed to populate the whole user object.
Here is the Conversation Schema:
const conversationSchema = new mongoose.Schema(
{
name: { type: String, required: true, unique: true },
messages: [{ message: { type: String }, authorId: { type: String } }],
lastMessage: {
authorId: { type: String },
snippet: { type: String },
read: { type: Boolean },
},
},
{ timestamps: true }
);
conversationSchema.index({ name: 1 });
module.exports = mongoose.model("Conversation", conversationSchema);
And here is my code:
router.get("/conversations", async (req, res) => {
try {
const { userId } = req.query;
const user = await User.findById({ _id: userId }).populate("messages");
.sort({ updatedAt: 1, "lastMessage.read": 1 });
return res.json({ messages: user.messages });
} catch (err) {
console.log("error", err);
return res.json({ errorType: "unread-messages-list" });
}
});
How to do this?

Mongoose post update middleware not working

I am use "mongoose": "^4.1.2". I have try to update a matchRate field when after a document being updated. But it doesn't work either not throw an any errors.
Here is code:
list.model.js
'use strict';
var mongoose = require('bluebird').promisifyAll(require('mongoose'));
import { Schema } from 'mongoose';
var ListSchema = new Schema({
name: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
emails: [],
emailColRef: String,
matchCount: Number,
totalCount: Number,
matchRate: Number,
state: {
type: String,
enum: ['pending', 'complete', 'invalid']
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
default: {
type: Boolean,
default: false
}
});
ListSchema
.virtual('count')
.get(() => this.emails.length);
ListSchema
.post('update', function() {
// this.update({},{ $set: { matchRate: this.matchCount / this.totalCount } });//Not working
//////-------------OR---------------//////
// this.matchRate=this.matchCount / this.totalCount;//Not working
console.log(this.matchCount);//undefined
console.log(this.totalCount);//undefined
console.log(this.matchRate);//undefined
});
export default mongoose.model('List', ListSchema);
list.controller.js
.....
.....
.....
var newList = {};
newList.name = name;
newList.emails = emails;
newList.emailColRef = emailColRef;
newList.state = status;
newList.matchCount = matchCount;
newList.totalCount = totalCount;
var query = { name: req.body.name };
List.update(query, newList, function(err, doc) {
// index(req, res);
if (err) {
console.log("Error in list update ", err)
return;
}
fs.unlink(req.file.path, function(err) {
if (err) {
console.log("Error in removing file", err)
return;
}
});
console.log('Update list with match status');
});

Resources