Intersection of key values between 2 different collections in MongoDB - node.js

I have 2 collections: bookings and timeslots.
models/booking.js:
var mongoose = require ('../config/db');
var Schema = require('mongoose').Schema;
var ObjectId = Schema.ObjectId;
var bookingSchema = new Schema({
start: {
type: Number,
required: true
},
end: {
type: Number,
required: true
},
date: {
type: Date,
required: true,
default: Date.now
}
});
models/time_slot.js:
var mongoose = require ('../config/db');
var Schema = require('mongoose').Schema;
var ObjectId = Schema.ObjectId;
var timeSlotSchema = new Schema({
start: {
type: Number,
required: true
},
end: {
type: Number,
required: true
},
date: {
type: Number,
required: true,
default: Time.Today
},
enabled: {
type: Boolean,
required: true,
default: true,
},
pickup: {
type: Boolean,
required: true,
default: true,
}
});
Both have a field start in common. I would like to be able to get the entries from the collection timeslots in which the value of start has occurred in bookings.
I have tried:
controllers/time_slot.js:
var timeSlotModel = require('../models/time_slot').model;
var Booking = require('./booking');
Booking.getBookings({}, function(err, bookings) {
if (err) {
console.error(err);
} else {
timeSlotModel.find({start: bookings.start}, function(err, slots) {
if (err) {
console.error(err);
} else {
return next(null, slots);
}
}
}
But that doesn't work, unsurprisingly, and I get the error:
MongooseError: Cast to number failed for value "undefined" at path "start"

You can do it like this:
Booking.getBookings({}, function(err, bookings) {
if (err) {
console.error(err);
} else {
// build array with unique "start" values from bookings
var starts = bookings
.map(booking => booking.start)
.filter((val, i, self) => self.indexOf(val) === i)
// find by these start values
var query = {start: {$in: starts}}
timeSlotModel.find(query, function(err, slots) {
if (err) {
console.error(err);
} else {
return next(null, slots);
}
}
}

Related

Node.js E11000 duplicate key error collection

I'm trying to create a reservation with node.js and express and mongoose!
This is my Schema:
let mongoose = require("mongoose");
let Schema = mongoose.Schema;
let reservationSchema = new Schema({
car: [
{
type: Schema.Types.ObjectId,
ref: "cars",
required: true,
unique: false,
},
],
client: [
{
type: Schema.Types.ObjectId,
ref: "users",
required: true,
unique: false,
},
],
request: {
type: "Date",
default: Date.now(),
},
from: {
type: "Date",
required: true,
},
days: {
type: "Number",
required: true,
},
});
let reservation = mongoose.model("Reservation", reservationSchema);
module.exports = reservation;
And this is my function that I'm using to make it work while the dates does not match
function check(reservations, newReservation) {
console.log("chegou");
return new Promise(function (resolve, reject) {
ReservationModel.find({}, function (err, reservations) {
console.log("chegou aqui lol");
console.log([reservations]);
console.log(newReservation);
if (err) reject(err);
reservations.forEach(myFunction);
function myFunction(reservations) {
console.log("Siga ze");
console.log(reservations.car);
console.log(newReservation.car);
if ((reservations.car = newReservation.car)) {
console.log("chegou ao if");
let date = reservations.from;
let days = reservations.days;
var result = new Date(date);
result.setDate(result.getDate() + days);
console.log(result);
console.log(newReservation.from);
if (newReservation.from >= result) {
console.log("devia funfar crlh");
resolve(newReservation);
} else {
console.log("Nao funfou");
}
} else {
console.log("fds nao da esta merda pqp");
}
}
});
});
}
It reaches the
if (newReservation.from >= result) {
console.log("devia funfar crlh");
resolve(newReservation);
So it should work, but when I get to the part when it is going to save to the database it gives me the error:
E11000 duplicate key error collection: rent-a-car.reservations index: car_1 dup key: { car: ObjectId('625af24b81b1edc90fdef50a') }
Saying that the car is already in use, and I have specifically in the Schema to not be unique.
What can I do?

How to use mongoose to make changes in two different collections in one nodejs query

In this application, I am trying to update a field value, if it is successful then I want to save into a log collection, however, not all the data are saved in the log collection, I am not sure if I am doing it the right way, would appreciate if someone could help out.
here is the query :
// both models(Log & Inventory are imported)
router.get("/add_product/:id/:num/:quantity/:order", (req, res) => {
var id = req.params.id;
var quantity = req.params.quantity;
var order = req.params.order;
// console.log('id----', id);
var num_mod = req.params.num;
var modified_count = parseInt(num_mod) - parseInt(quantity);
console.log("num_mod----", num_mod);
Inventory.findByIdAndUpdate(id, { quantity: parseInt(num_mod) }, { new: true }, function(
err,
inventory
) {
if (err) {
console.log("err", err);
res.status(500).send(err);
} else {
console.log(inventory.name);
const newLog = new Log({
name: inventory.name,
description: inventory.description,
price: parseInt(inventory.price),
quantity: parseInt(inventory.quantity),
modified_quantity: parseInt(modified_count),
itemDest: order //this is not being saved
});
newLog.save(function(err, Log) {
if (err) {
console.log(err);
} else {
console.log("add log success");
res.send(inventory);
}
});
}
});
});
URL from front end :
// order is a string
here is the Log schema :
const mongoose = require("mongoose");
const LogSchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
modified_quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean,
itemDest: String
},
{ timestamps: true }
);
// Create model from the schema
const Log = mongoose.model("Log", LogSchema);
// Export model
module.exports = Log;
and here is the inventory schema
const mongoose = require("mongoose");
//create Schema
const InventorySchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean
},
{ timestamps: true }
);
// Create model from the schema
const Inventory = mongoose.model("Inventory", InventorySchema);
// Export model
module.exports = Inventory;
My issue is with this line "itemDest: order" in the query, I intend to save the value of "order" extracted from "req.params.order" into "itemDest" but it doesn't save.

MongooseError [ParallelSaveError]: Can't save() the same doc multiple times in parallel

I am having an issue with mongoose and nodejs. May be i am writing wrong code or any other problem please help. Here is my controller file. alldata.save gives [ParallelSaveError]
let createData = async function(req,res,next) {
let body = req.body;
let alldata = new League(body);
let start_time = new Date().getTime();
try {
await Leaguecategories.find({})
.then(async function(categories) {
categories.forEach(async function(category) {
//here i am assigning foreign key
alldata.league_category_id = category._id;
await alldata.save(function(err, book){
if(err){
console.log(err);
}else{
res.send({status: 0, statusCode:"success", message: "Successfully inserted."})
}
});
})
})
}
catch (error){
return res.send({status : 1 , statusCode : "error" , message : error.message})
}
}
Here is my Leaguecategories model
var mongoose = require('mongoose');
const league_categories = new mongoose.Schema({
name: {
type: String,
required: true
},
active: {
type: String,
required: true
},
create_date: {
type: Date,
required: true,
default: Date.now
},
league_type_id: {
type: String,
required: 'league_type',
required:true
}
})
module.exports = mongoose.model('Leaguecategories', league_categories)
Here is my League model
var mongoose = require('mongoose');
const league = new mongoose.Schema({
title: {
type: String,
required: true
},
pool_price: {
type: Number,
required: true
},
entry_fee: {
type: Number,
required: true
},
total_spots: {
type: Number,
required: true
},
start_time: {
type: Date,
required: true
},
end_time: {
type: Date,
required: true
},
create_date: {
type: Date,
required: true,
default: Date.now
},
active: {
type: String,
required: true
},
league_category_id: {
type: String,
ref: 'Leaguecategories',
required:true
}
})
module.exports = mongoose.model('League', league)
You have to create new instance of League each time. Like this:
categories.forEach(async function(category) {
//here i am assigning foreign key
let alldata = new League(body);
alldata.league_category_id = category._id;
...
});
Suggestion:
Why are you using both async/await and .then()? You should use only one of them. Also, there are some other problems.
await won't work inside forEach
You are calling res.send() every time you call .save(). This might end up throwing an error as well.
You can refactor the code like this.
try {
const categories = await Leaguecategories.find({});
const promises = categories.map(function (category) {
//here i am assigning foreign key
let alldata = new League(body);
alldata.league_category_id = category._id;
return alldata.save();
});
await Promise.all(promises);
res.send({ status: 0, statusCode: "success", message: "Successfully inserted." })
} catch (error) {
return res.send({ status: 1, statusCode: "error", message: error.message });
}

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');
});

Mongoose: value from Model

I have the following model:
var requestSchema = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
})
I now want to get the price using mongoose and I am not sure which command I have to use.
I tried:
var pricy = _.first(_.where(request.price));
and it does not work, I get undefined even through through other queries in the same file I can get "shipping".
Getting the shipping type works with the following command:
var shipping = _.first(_.where(request.shipping, { type: shippingType }));
Am I using the wrong command?
You should be able to use the select method as follows:
// find a request
var query = Request.findOne();
// selecting the `price` field
query.select('price');
// execute the query at a later time
query.exec(function (err, request) {
if (err) return handleError(err);
console.log('The price is $%s.', person.price) // The price is $6.92
});
or if passing a callback:
var Request = mongoose.model('Request', requestSchema);
// find each request with a country matching 'Zimbabwe', selecting the `price` field
Request.findOne({ 'country': 'Zimbabwe' }, 'price', function (err, request) {
if (err) return handleError(err);
console.log('The price is $%s.', request.price) // The price is $6.92.
});
First, you need to create your schema like that:
var items = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
});
After that you need to compile the new schema and add it to the database:
items = mongoose.model("Items", items); // The table name will be "Items"
When the model is created, you can execute your query (find or findOne):
items.findOne({price: request.price}, function (error, item) {
if (error) {
console.log(error);
} else {
console.log(item);
}
});
The full code:
var mongoose, Schema;
mongoose = require("mongoose");
Schema = mongoose.Schema;
var items = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
});
items = mongoose.model("Items", items);
items.findOne({price: request.price}, function (error, item) {
if (error) {
console.log(error);
} else {
console.log(item);
}
});

Resources