Error: TypeError: user.insertOne is not a function using mongoose - mongodb

I'm having difficulty creating the routes to send to MongoDB.
When I return user, it returns the full database. This goes for using User or 'user'.
User is a model
let User = require('../models/user.model');
User.findById(req.params.id)
.then(user => {
if (!user)
res.status(404).send("data is not found");
else
for(var key in req.body.proposal) {
//res.send(user.proposal)
//res.send(user)
//res.send(User.username)
user.proposal.insertOne(
{
"uid" : req.body.proposal[key].uid,
"clientEmail" : req.body.proposal[key].clientEmail,
"summary" :req.body.proposal[key].summary,
"terms" :req.body.proposal[key].terms,
"form" :req.body.proposal[key].form
} //update
)
}
user.save()
.then(user => res.json(user))
.catch(err => res.status(400).json('Error: ' + err));
})
.catch(err => res.status(400).json('Error: ' + err));
});
Thank you in advanced!

It should be something like this :
let proposalArr = [];
for (const key in req.body.proposal) {
proposalArr.push({
uid: req.body.proposal[key].uid,
clientEmail: req.body.proposal[key].clientEmail,
summary: req.body.proposal[key].summary,
terms: req.body.proposal[key].terms,
form: req.body.proposal[key].form
});
}
user.proposal = proposalArr;
user.save().............
You can't use .insertOne on result of database query, it's a function of mongoose model to insert new document to collection but not to insert new fields to objects. You need to do just like adding new fields to json object using .js code, but mongoose will keep track of object's changes & when you use .save() it can update the document in collection with all those changes.
Instead of two DB calls, you can do that in one call, Check : .findByIdAndUpdate() & try below sample code :
let proposalArr = [];
for (const key in req.body.proposal) {
proposalArr.push({
uid: req.body.proposal[key].uid,
clientEmail: req.body.proposal[key].clientEmail,
summary: req.body.proposal[key].summary,
terms: req.body.proposal[key].terms,
form: req.body.proposal[key].form
});
}
User.findByIdAndUpdate(
req.params.id,
{
proposal: proposalArr
},
{ new: true }
)
.then(user => {
if (!user) res.status(404).send("data is not found");
res.json(user);
})
.catch(err => res.status(400).json("Error: " + err));

Related

MongoDB and triggers

I have a post call that inserts records in an Atlas mongodb database, the Atlas service has a trigger active to increment a correlative field (no_hc), then I make a query to retrieve that correlative field with the _id generated in the insert of the document. I put the code below so that they can tell me what I am doing wrong since this code sometimes returns null the field no_hc. Thanks since now
I add information about what I need to execute. I have a collection on which every time a document is added the mongodb server executes a trigger to increment a certain field, the problem is that the findoneandupsert query returns the inserted document with the autoincrement field set to null, since apparently the trigger is executed after the result of findoneandupsert is returned, how can I solve this issue?
router.post('/admisionUpsert', (req, res) => {
admisionUpsert(req.body)
.then(data => res.json(data))
.catch(err => res.status(400).json({ error: err + ' Unable to add ' }));
})
async function admisionUpsert(body) {
let nohc = body.no_hc
delete body['no_hc'];
let id;
let noprot
await Paciente.findOneAndUpdate(
{ no_hc: nohc },
{
apellido: body.apellido,
nombre: body.nombre,
sexo: body.sexo,
no_doc: body.no_doc,
fec_nac: body.fec_nac,
calle: body.calle,
no_tel: body.no_tel,
email: body.email
}, {
new: true,
upsert: true
}
)
.then(data => { id = data._id })
console.log("id pac", id)
Paciente.findOne({ _id: id }).then(data => { nohc = data.no_hc })
console.log("nohc pac", nohc)
await Protocolo.findOneAndUpdate(
{ no_prot: "" },
{
cod_os: body.cod_os,
no_os: body.no_os,
plan_os: body.plan_os,
no_hc: nohc,
sexo: body.sexo,
medico: body.medico,
diag: body.diag,
fec_prot: body.fec_prot,
medicacion: body.medicacion,
demora: body.demora
}, {
new: true,
upsert: true
}
)
.then(data => { id = data._id })
console.log("id prot", id)
Protocolo.findOne({ _id: id }).then(data => { noprot = data.no_prot })
console.log("noprot prot", noprot)
let practicasProtocolo = []
body.practicas_solicitadas.map((practica, index1) => {
practicasProtocolo.push({
no_prot: noprot,
cod_ana: practica.codigo,
cod_os: practica.cod_os,
estado_administrativo: practica.estado_administrtivo,
estado_muestra: practica.estado_muestra,
estado_proceso: practica.estado_proceso,
})
practica.parametro.map((parametro, index) => {
par = parametro.codigo
tipo_dato = parametro.tipo_dato
if ((tipo_dato === "numerico") || (tipo_dato === "frase") || (tipo_dato === "codigo")) {
practicasProtocolo[index1][par] = null;
}
})
})
console.log(practicasProtocolo)
practicasProtocolo.map(async (practica, index) => {
await new Practica(practica).save()
})
return { nohc: nohc, noprot: noprot }
}

Inserting a record from a mongoose model.statics function

I want to create a static function on a mongoose "log" module, which would allow me to write a message as a log entry.
How do I access the model from within the static function? Can I use this.model like below? I don't want to simply use native MongoDB insert command, because I want the model to validate the input, etc.
// ... schema defined above...
var Log = mongoose.model('Log', LogModelSchema)
Log.statics.log = function(message) {
var x = new this.model({message: message})
x.save()
.then(() => { .. do something .. }
.catch((err) => { .. handle err .. }
}
Is this the way it's supposed to be done?
You can make it work like this using this.create:
const mongoose = require("mongoose");
const logSchema = new mongoose.Schema({
message: String
});
logSchema.statics.log = function(message) {
this.create({ message: message })
.then(doc => console.log(doc))
.catch(err => console.log(err));
};
module.exports = mongoose.model("Log", logSchema);
Now you can use this in your routes like this:
Log.log("test");
or just return promise from statics:
logSchema.statics.log = function(message) {
return this.create({ message: message });
};
And use like this:
const Log = require("../models/log");
router.get("/log", (req, res) => {
Log.log("test")
.then(result => {
console.log(result);
res.send("ok");
})
.catch(err => {
console.log(err);
res.status(500).send("not ok");
});
});

Mongoose cannot findOne({_id : id}) with copied documents

I copied documents from a local database to my production database and when I try to get the document by Id by running model.findOne({_id : id}) and mongoose returns nothing. I am copying the documents over with the same Id, but I also tried with a new Id. I can find the document in the database and confirm that the JSON is correct, the Id is correct, etc and it won't find it. The documents I did not copy and where generated via my app still query fine with the findOne command. So, I have no idea what's going on
any help is greatly appreciated, thanks
groups.crud
getGroupById(id: string) {
logger.debug(".getGroupById id: " + id);
return new Promise(function(resolve, reject) {
GroupsModel.findById(id)
.populate('createdBy')
.then(function (group) {
logger.debug(".getGroupById");
if(group.createdBy.privacySettings.useUserName) {
group.createdBy.firstName = '';
group.createdBy.lastName = '';
}
resolve(group);
})
.catch(function(error) {
reject(error);
});
});
}
groups.routes
getGroupById(req, res, next) {
logger.debug('.getGroupById: BEG');
let id = req.params.id;
return groupsCrud.getGroupById(id)
.then(function(group) {
if(group) {
logger.debug('.getGroupById: get by id success');
let response = {
data : group
}
logger.debug('.getGroupById: response: ' + response);
res.json(response);
}
else {
logger.debug('.getGroupById: get by id failed 1');
res.status(404).json({ status : 404, message : "Group not found."});
}
})
.catch(function(error) {
logger.debug('.getGroupById: get by id failed 2 err = ' + JSON.stringify(error, null, 2));
res.sendStatus(404);
});
}

Error constructing as per schema

I have the following defined in my server.js,
//server.js
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var userSchema = new Schema({
"userName": {
type: String,
unique: true
},
"password": String,
"loginHistory": [{
"userAgent": String,
"dateTime": Date
}]
});
var User;
module.exports.initialize = () => {
return new Promise(function (resolve, reject) {
let db = mongoose.createConnection("mongodb://<dbuser>:<dbpassword>#ds237409.mlab.com:37409/web322_a6");
db.on('error', (err)=>{
reject(err); // reject the promise with the provided error
});
db.once('open', () => {
User = db.model("users", userSchema);
resolve();
});
})
};
I have a function that is called when posting to my app.post('/register') route, and it basically builds a new User, then assigns it to the passed data, and resolves it afterwards.
module.exports.registerUser = (userData) => {
return new Promise((resolve, reject) => {
if (userData.password != userData.password2) {
reject("Passwords do not match!");
}
let newUser = new User(userData);//<!-- 'Error: TypeError: User is not a constructor'
newUser.save((err) => {
if(err.code == 11000) {
reject("Username already taken");
} else {
reject("Error creating User: " + err);
}
// exit the program after saving
//process.exit();
resolve();
});
})
}
At first I thought I've misdefined User, but I seem to have initialized it properly, as per the MongoDB documentation. Any thoughts? It keeps throwing Error: TypeError: User is not a constructor
EDIT: /post / register
app.post("/register", (req, res) => {
console.log("entering1");
dataServiceAuth.registerUser(req.body).then((data) => {
res.render('register', {successMessage: "User Created"});
}).catch((err) => {
console.log("Error: " + err);
res.render('register', {errorMessage: err, userName: req.body.userName});
})
});
My error was in,
let db = mongoose.createConnection("mongodb://<dbuser>:<dbpassword>#ds237409.mlab.com:37409/web322_a6");
The greater than and less than signs are not to be used. Proper string:
let db = mongoose.createConnection("mongodb://dbuser:dbpassword#ds237409.mlab.com:37409/web322_a6");

GraphQL x MongoDB

I'm trying to read some data from a mongodb database with graphql and mongoose but everytime I query the db it returns null but no error is thrown.
Here's the code:
// Controller.js
exports.user_read = function(id) {
return new Promise((resolve, reject) => {
Contact.findById(id, function(err, user) {
err ? reject(err) : resolve(user);
}
});
}
// Resolver.js
var contact = require('Controller');
...
// root object passed as rootValue to graphqlHTTP
getUser: ({ id }) => {
contact.user_read(id)
}
...
Any tips and help would be appreciated.
P.S. This also seems to be happening with all my queries which take the same Promise format in the controller.js file.
You need to await contact.user_read(id). Without the await, you are simply sending back a Promise. It's most likely pending when it is returned, therefore the null return.
Including Daniel Rearden's suggestion to get rid of the extra Promise, here's what your code would look like:
// Controller.js
exports.user_read = async id => {
return Contact.findById(id, (err, user) => {
err ? reject(err) : resolve(user);
});
}
// Resolver.js
var contact = require('Controller');
...
// root object passed as rootValue to graphqlHTTP
getUser: ({ id }) => {
return await contact.user_read(id)
}
...