NodeJS 'mongodb' client update function not working sometimes - node.js

mongodb client version: 3.1.10
I am using hosted mongo db server on Mlab.com: Shared Production-Ready cluster.
var dbo = db.db(DB);
var collection = dbo.collection('schedule');
var query = {email:userEmail};
let availability = (availabilityArg==="offQ")?"no":"yes";
let note = (availabilityArg==="offQ")?"Off Queue":"";
var data = {available:availability,notes:note};
collection.update(query,{$set:data},function(err,data){
if(err)
console.log("DB find error.");
else{
console.log(userEmail+((availabilityArg==="offQ")?" off the queue":" back in queue"));
}
});
The above works 95% of the time. 5% of the time, the DB does not get updated at all.
95%: The DB get's updated based on the availabilityArg. If it is offQ, the available attribute will be set to no. If it is onQ, the available attribute will be set to yes. The notes attribute also gets updated accordingly.
5%: The DB does not get updated at all. There's no change to the available attribute and the notes attribute. Though I see the console.log statement with the email ID and the off the queue/back in queue message.
It just doesn't make sense.
PS:
function(db,userEmail, availabilityArg)

I took your code and re-imagined it as follows, I hope it helps.
/*
I am not sure what is going on behind here
so I'll just comment it out, and show you
an implementation that works, which you can
repurpose.
*/
// var dbo = db.db(DB);
// var collection = dbo.collection('schedule');
/*
NOTE: Below is the an example model for handling data using mongoose,
This should be in a separate file which you would import
*/
const mongoose = require('mongoose');
const schema = new mongoose.Schema({
email: {
required: true,
type: String,
require: true
},
availability: {
required: true,
type: String,
default: ''
},
notes: {
required: true,
type: String,
default: ''
}
});
// If in the same file (not advisable)
const Schedule = mongoose.model('Schedule', schema, 'schedule_collection');
// Or export (advisable)
module.exports = mongoose.model('Schedule', schema, 'schedule_collection');
// NOTE: Below is a re-imagined version of your code
const findQuery = { email: userEmail };
const availability = availabilityArg === 'offQ' ? 'no' : 'yes';
const notes = availabilityArg === 'offQ' ? 'Off Queue' : '';
// NOTE: For updating the document
const updateQuery = {
availability: availability,
notes: notes
};
// NOTE: Using findOneAndUpdate of the Model
Schedule.findOneAndUpdate(findQuery, updateQuery, (err, _) => {
if (err)
console.log("DB error.");
else {
console.log(userEmail + ((availabilityArg === "offQ") ? " off the queue" : " back in queue"));
}
});

Related

Why am I not able query ( User.findOne() ) my mongoDB after setting up a Schema?

I can't seem to query my MongoDB after setting up the MongoDB schema. I don't understand where I am going wrong with my MongoDB schema, any help is appreciated!
I WAS earlier successful in querying my mongodb before creating a schema, using queries like this:
const uri = process.env.MONGODB_URI;
const client = new MongoClient(uri);
const result = await client.db("inride_adverts").collection("adverts").findOne({OrgEmail: OrgEmailToSignIn});
However, according to a YouTube tutorial am following (10:40 mins), after setting up a mongodb schema, I am NOT successful in using the following query to interact with my mongodb:
User.findOne( {OrgEmail: signUpEmail} ).exec();
Find below my simple User Schema:
./models/User.js
import { mongoose} from 'mongoose';
const UserSchema = new mongoose.Schema({
OrgName: {
type: String,
required: true
},
OrgEmail: {
type: String,
required: true
},
OrgPwd: {
type: String,
required: true
}
}, { collection: 'adverts' });
export const User = mongoose.model('User', UserSchema);
Also, find below my server.js file
./server.js
import express from 'express';
import { User } from './models/User.js';
import mongodb from 'mongodb';
import { mongoose} from 'mongoose';
mongoose.connect(db, { useNewUrlParser: true })
mongoose.connect(db, { useNewUrlParser: true })
.then( () => console.log("MongoDB Connected..." ))
.catch(error => console.log(err))
app.route('/advertiserRegister')
.post( async (req, res) => {
let formData = req.body;
let signUpName = formData.signUpName;
let signUpEmail = formData.signUpEmail;
let signUpPwd = formData.signUpPwd;
console.log("signUpName: " +signUpName);
console.log("signUpEmail: " +signUpEmail);
console.log("signUpPwd: " +signUpPwd);
if(signUpPwd !== signUpPwdConfirm){
console.log("Passwords arent EQUAL!");
return 0;
} else {
try{
console.log("signUpEmail>>> : " + signUpEmail );
// Validation passed!
const testing = await User.findOne( {OrgEmail: signUpEmail} ).exec();
console.log("testing >>> : " ,testing );
res.redirect('/advertiserLogin')
} catch {
//console.error('error', code);
console.log("Error logging in ");
res.redirect('/advertiserRegister')
};
}
});
The server.js file yields:
MongoDB Connected...
signUpName: Merc Enterprise LTD
signUpEmail: hundredcent.a#gmail.com
signUpPwd: 555
signUpEmail>>> : hundredcent.a#gmail.com
testing >>> : **null**
Error logging in
Turns out that the reason I was NOT able to query my collection was due to the fact that I was unknowingly querying the incorrect collection being: adverts under the incorrect database being: inride_adverts.
I came to understand and realise that In my ./models/User.js, the mongoose.model('User', UserSchema); code creates a new database in Atlas MongoDB called test and creates a totally new collection called User.
Having understood this, I am able to populate and query this collection successfully!

Mongodb schema emptied after seconds

When i am making a request to save a new object to my mongodb, it gets saved, and after seconds everything in that schema disappears.
In the screenshot below you can see this happening, where with the first command i check that the schema is empty, then i make a request to save a new object which is done successfully, and after a few seconds you can see that the object has disappeared.
The express endpoint looks like so:
router.post('/bookdate',passport.authenticate('jwt', {session:false}), (req, res) => {
const userId = req.user._id
const appartmentNumber = req.user.apartmentNumber;
const requestedDate = req.body.requestedDate;
const bookingZone = req.body.bookingZone;
const newBooking = new Booking({
'apartmentNumber': appartmentNumber,
'dateOfBooking': requestedDate,
'bookingZone': bookingZone
});
if (req.user.hasTimeBooked) {
res.json({booked: false, msg: 'There is already a booking for this user.'})
} else {
if (typeof newBooking.requestedDate !== undefined && typeof newBooking.bookingZone !== undefined) {
Booking.addBooking(newBooking, (err, result)=>{
if(err){
res.json({booked: false, msg: err})
} else {
res.json({booked: true, msg: result})
}
})
} else {
res.json({booked: false, msg: 'Undefined parameters Date or Zone'})
}
}
});
and the mongoose schema looks like so
const mongoose = require('mongoose');
const config = require('../config/database');
const BookingSchema = mongoose.Schema({
apartmentNumber:{
type: Number,
unique: true
},
dateOfBooking:{
type: Date
},
bookingZone:{
type: String
}
});
const Booking = module.exports = mongoose.model('bookings',BookingSchema, 'bookings');
module.exports.addBooking = function(bookingObj, cb){
var newBooking = new Booking(bookingObj);
newBooking.save(cb);
}
There are no errors appearing in console, and i am not quite sure where to start looking.
Thanks in advance!
EDIT
The result from db.bookings.getIndices() is shown in the screenshot here
From the getIndices output I could see you've created an TTL index on dateOfBooking so it gets deleted after 60 seconds in the backend
From the mongo docs TTL index
TTL indexes are special single-field indexes that MongoDB can use to
automatically remove documents from a collection after a certain
amount of time or at a specific clock time

MongoDB : Missing the key _id in the item

I have been given some code to modify. It is a Node.js app using Mongoose to interact with a MongoDb instance. In Mongoose several schemas were already set up and I've added a few. Among those are these two schemas which break apart a previously existing schema (which was working fine with small data):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var MapConvertedProjectSchema = new Schema(
{
project_id : {
type: String,
default: ""
},
dataset_id : {
type: String,
default: ""
},
properties:{
type: {},
default: {}
}
});
MapConvertedProjectSchema.pre('save', function(next) {
next();
});
mongoose.model('MapConvertedProject', MapConvertedProjectSchema);
and
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var MapConvertedLayerSchema = new Schema(
{
parent_id:
{
type: mongoose.Schema.Types.ObjectId
},
class:
{
type: String,
default: 'MapLayer',
trim: true
},
properties:
{
type: {},
default: {}
}
});
//Hook a pre save method to clean date
MapConvertedLayerSchema.pre('save', function(next) {
next();
});
mongoose.model('MapConvertedLayer', MapConvertedLayerSchema);
I use the MapConvertedLayer schema like so:
var mongoose = require('mongoose');
var LayerConverted = mongoose.model('MapConvertedLayer');
var newLayer = new LayerConverted();
//newLayer._id is automatically populated with a value
//... add other properties
newLayer.save(function(err)
{
if(err)
{
//...
}
});
This works without any issues that I can discern. However if I try similar code with MapConvertedProject I get an error:
var mongoose = require('mongoose');
var ProjectConverted = mongoose.model('MapConvertedProject');
var map_converted = new ProjectConverted();
//map_converted._id is undefined
//I tried adding the comment below to create an _id manually, but it didn't make a difference when I tried to save
//map_converted._id = mongoose.Types.ObjectId();
console.log("Project Converted ID: " + map_converted._id);
//... fill out the other properties on the schema
map_converted.save(function(err)
{
if(err)
{
//...
}
});
The save generates this error:
ValidationException: One or more parameter values were invalid: Missing the key _id in the item
Does anyone know what is causing this?
I figured this out. There was another place in the code that had a dynamoose model with the same name that was messing things up. I was able to remove all references to dynamoose since it doesn't appear to be used anymore and that cleared up this issue.

Node Mongoose - saving embedded documents on API once receiving mongoId

I would like to know the best approach to solve the current scenario.
I've got a node API which uses mongoose and bluebird. And some Android clients will post "movement" entities to it.
(Question at the end).
Let's say movement-model.js exports the Schema, and looks like this:
"use strict";
const mongoose = require('mongoose');
const _movementSchema = {
movementId: { type: Number, requried: true },
relMovementId: Number,
_party: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Party' }
}
module.exports = mongoose.Schema(_movementSchema, {collection: 'movement'});
And related exported Schema on party-model.js is as follows:
"use strict";
const mongoose = require('mongoose');
const _partySchema = {
active: { type: Boolean, default: true },
name: { type: String, trim: true, required: true },
logo: { type: Buffer },
coordenates: { lat: Number, long: Number },
startOn: { type: Date, required: true },
endOn: { type: Date, required: true }
}
module.exports = mongoose.Schema(_partySchema, {collection: 'party'});
Android client would send the JSON with ObjectId and not full populated object. So when the POST comes, I'm using it directly (i.e: let _movement = req.body;) and on the movement-dao.js I've got the createNew method and I'm exporting the Model:
"use strict";
const mongoose = require('mongoose');
const Promise = require('bluebird');
mongoose.Promise = Promise;
const movementSchema = require('../model/movement-model');
movementSchema.statics.createNew = (movement) => {
return new Promise((resolve, reject) => {
if (!_.isObject(movement)) {
return reject(new TypeError('Movement is not a valid object.'));
}
let _something = new Movement(movement);
_something.save((err, saved) => {
err ? reject(err)
: resolve(saved);
});
});
}
const Movement = mongoose.model('Movement', movementSchema);
module.exports = Movement;
What I want to accomplish is to: save the movement collection with the _party as the full party document is at the moment of the save, I mean an embedded document of a copy of the Party document, which will not be affected by the updates done to the Party document in the future.
While I cannot change the Android Client, so I will still be getting only the ObjectId from it.
JSON example of what Android client will post: {"movementId":1, "relMovementId":4138, "_party":"58dbfe26194cfc5a9ec9b7c5"}
I'm confused now, and not sure if due to the way Android is posting the JSON, I need two schemas; one for the object received (i.e: with ObjectId and ref to Party) and a second one for the object persisted (i.e: with the schema referenced _party: Party.Schema) or if I could do something simpler as some populate prior to save... or what.
For the sake of closing this up:
I've implemented one of the approaches I had in mind while writing the question. Movement schema changed so that: _party: Party.Schema
When I get a POST to create a new movement I do a getById and use the result of that exec to populate the value as an embedded doc.

Objects returned by Mongoose queries have no attributes

I currently have 3 MongoDB databases to which I connect from a Node.js app using mongoose.createConnection(...). For each db, I define schemas and models for all collections in the db. The problem I have is that when I query a collection, the results returned do not have any attributes set. However, using node-inspector, I can see that the attributes are loaded correctly from the db because they are present in the _doc attribute.
Example (some code is omitted):
var mongoose = require('mongoose');
// Connect to a db
var db = mongoose.createConnection();
var options = { auto_reconnect: true };
db.open(args.host, args.db, args.port, options, function(error, connection) {
var buildModel = require('../models/' + dbName + '/schema.js');
buildModel(db);
}
// Define schemas and models (in schema.js). This is the `buildModel` function from above.
module.exports = function(mongoose) {
var Group = new Schema({
name: { type: String, required: true },
companyId: { type: ObjectId, required: true }
});
mongoose.model("Group", Group, 'groups');
};
// Querying
var Group = getDb('db1').model('Group');
Group.find({}, function(error, groups) {
// Here I get all documents in the groups collection, but the attributes
// name and companyId are not set.
groups.forEach(function(group) {
// name and companyId are undefined
console.log('undefined' == typeof group.name); // true
console.log('undefined' == typeof group.companyId); // true
// _doc attribute is populated
console.log(group._doc.name); // 'Group 1'
});
});
The question is, am I forgetting to do something when I connect? I have also tried to specify the attributes to fetch using populate after calling find, but with no success.
I am using MongoDB 2.4.3, Node.js 0.10.6 and Mongoose 3.6.11.

Resources