Mongoose findByIdAndUpdate fails, returns null - mongodb

I've got a Mongoose schema for an object called Plot which works fine when it comes to saving. However, when I try to update those plots with the code below, it fails, returning null:
exports.updatePlot = async (req, res) => {
let updates = { ...req.body.props };
const id = updates._id;
if (updates.plannedYield) {
const plannedYield = Number(updates.plannedYield);
const metrics = {
yield: { day120CustomerEstimation: plannedYield }
};
updates.metrics = metrics;
delete updates.plannedYield;
}
console.log(updates);
try {
console.log('updating plot');
const updatedPlot = await Plot.findByIdAndUpdate(id, updates, {
new: true
});
if (!updatedPlot) {
console.log("couldn't update plot");
}
console.log(('updated plot saved:', updatedPlot));
res.json({
updatedPlot
});
} catch (e) {
console.log('error', e);
return res.status(422).send({
error: { message: 'e', resend: true }
});
}
};
This results in the following console output:
{ id: '5aa65801c97d496ef457b802',
metrics: { yield: { day120CustomerEstimation: 1 } } }
updating plot
couldn't update plot
null
Can anyone suggest a fix? I've tried casting id to ObjectId, which didn't do the trick.

Related

Mongoose Error stating that it cannot populate a path because its not in my schema - but im not populating anything?

I have two routes in my server. Both routes are identical minus one using $push and one using $pull. The $pull route works as it should but always responds with an error of
"MongooseError: Cannot populate path scenes because it is not in
your schema. Set the strictPopulate option to false to override."
while the $push route works perfect and responds accordingly. I am very confused as to why I am getting a populate error considering I am not populating? I do have a 'scenes' property but not in either Model being used in these routes.
router.put('/scene/:sceneId/addactor/:actorId', async (req, res) => {
const actorId = req.params.actorId;
const sceneId = req.params.sceneId;
try {
const actor = await Actor.findById(actorId);
await Scene.findByIdAndUpdate(sceneId, { $push: { actors: actor } }, { new: true }).then(dbSceneData => {
res.status(200).send(dbSceneData);
})
} catch (error) {
res.status(400).send(`An Error Ocurred: ${error}`);
}
});
router.put('/scene/:sceneId/removeactor/:actorId', async (req, res) => {
const actorId = req.params.actorId;
const sceneId = req.params.sceneId;
try {
const actor = await Actor.findById(actorId);
await Scene.findByIdAndUpdate(sceneId, { $pull: { actors: actor } }, { new: true }).then(dbSceneData => {
res.status(200).send(dbSceneData);
})
} catch (error) {
res.status(400).send(`An Error Ocurred: ${error}`);
}
});

Mongodb .post unable to add data to the collection

I am trying to take user input and then add a drug(medicine) to MongoDB. But it is not working and I am getting the error "Add proper parameter first". The user input should be patient name, drug name, dosage, frequency, adherence, and reason for not taking medicine. Please help!
app.post("/add-drug", (req, res) => {
try {
if (req.body && req.body.patient_name && req.body.drug_name && req.body.dosage && req.body.frequency && req.body.adherence && req.body.reason) {
let new_drug = new drug();
new_drug.patient_name = req.body.patient_name
new_drug.drug_name = req.body.drug_name;
new_drug.dosage = req.body.dosage;
new_drug.frequency = req.body.frequency;
new_drug.adherence = req.body.adherence;
new_drug.reason = req.body.reason;
new_drug.user_id = req.user.id;
new_drug.save((err, data) => {
if (err) {
res.status(400).json({
errorMessage: err,
status: false
});
} else {
res.status(200).json({
status: true,
title: 'Drug Added successfully.'
});
}
});
} else {
res.status(400).json({
errorMessage: 'Add proper parameter first!',
status: false
});
}
} catch (e) {
res.status(400).json({
errorMessage: 'Something went wrong!',
status: false
});
}
});
The model file looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
drugSchema = new Schema( {
patient_name: String,
drug_name: String,
dosage: Number,
frequency: Number,
adherence: Number,
reason: String,
user_id: Schema.ObjectId,
}),
drug = mongoose.model('drug', drugSchema);
module.exports = drug;
it is supposed to be <field>:<value> inside your app.post method, not <field>=<value>
The new_drug.save() method is asynchronous, so it returns a promise that you can await on:
app.post("/add-drug", async(req, res) => {
//...
await new_drug.save();
})

Calling mongodb insert,find functions from another class in react native , returns undefined

This is my first class where I defined all db functions.
import React,{Component} from 'react';
var Datastore = require('react-native-local-mongodb')
, db = new Datastore({ filename: 'asyncStorageKey', autoload: true });
export default class RDDBManager {
static dbmanager = null;
static getInstance() {
if (RDDBManager.dbmanager == null) {
RDDBManager.dbmanager = new RDDBManager();
}
return this.dbmanager;
}
constructor () {
}
//insert items
insertItem(item){
var json = item.toJsonString();
console.log("Inside insertItem ::: "+json);
db.insert(json,function(err,newDos){
return newDos;
});
}
//read single item
readItem(itemId){
db.findOne({ id: itemId }, function (err, doc) {
return doc;
});
}
//read all items
readAllItems(){
db.find({}, function (err, docs) {
return docs;
});
}
getModalData(modalName) {
this.readAllItems();
}
//update
updateItem(itemId){
db.update({ id: itemId }, { $set: { system: 'solar system' } }, { multi: true }, function (err, numReplaced) {
});
}
//delete item
deleteItem(itemId){
db.remove({ id: itemId }, {}, function (err, numRemoved) {
return numRemoved;
});
}
}
But,when I try to call these functions from another class,the data is undefined.
loadDataFromDB() {
var items = RDDBManager.getInstance().readAllItems();
console.log("Items ======>>>>>> "+items);
}
the value of items is undefined.
This is because you are not doing things right, Your readallitems is async in nature so you have to do something like this:-
//read all items
readAllItems(callback){
db.find({}, function (err, docs) {
callback(docs);
});
}
And For calling something like this:-
loadDataFromDB() {
RDDBManager.getInstance().readAllItems(function(items){
console.log("Items ======>>>>>> "+items);
});
}
Alternatively, you can use promise or Async await also.

Waterline ORM assign the result of find to a variable

I want to combine the results of 2 queries and then return them as one, like this:
test: async (req, res) => {
const valOne = TableOne.find({ id: id })
.exec((err, result) => {
if (err) {
res.serverError(err);
}
return result;
});
const valTwo = TableTwo.find({ id: id })
.exec((err, result) => {
if (err) {
res.serverError(err);
}
return result;
});
const data = {
keyOne: valOne,
keyTwo: valTwo,
};
res.json(data);
}
I understand above code won't return because it's async. How can I achieve this?
There is not much info you supply: node version, sails version, etc.
There are several approaches here:
1. Using promises
2. Using callback chaining
3. Using await/async
If you use sails 1.0 and node >= 8, your best bet is to use await/async, so your code should work like that:
test: async (req, res) => {
let valOne, valTwo;
try {
valOne = await TableOne.find({ id: id });
valTwo = await TableTwo.find({ id: id });
} catch (err) {
return res.serverError(err); //or res.badRequest(err);
}
const data = {
keyOne: valOne,
keyTwo: valTwo,
};
res.json(data);
}

Using design documents in pouchDB with crypto-pouch

After testing pouchDB for my Ionic project, I tried to encrypt my data with crypto-pouch. But I have a problem with using design documents. I used the following code:
One of my design documents:
var allTypeOne = {
_id: '_design/all_TypeOne',
views: {
'alle_TypeOne': {
map: function (doc) {
if (doc.type === 'type_one') {
emit(doc._id);
}
}.toString()
}
}
};
For init my database:
function initDB() {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
return _db.crypto(password)
.then(function(){
return _db;
});
// add a design document
_db.put(allTypeOne).then(function (info) {
}).catch(function (err) {
}
}
To get all documents of type_one:
function getAllData {
if (!_data) {
return $q.when(_db.query('all_TypeOne', { include_docs: true}))
.then(function(docs) {
_data = docs.rows.map(function(row) {
return row.doc;
});
_db.changes({ live: true, since: 'now', include_docs: true})
.on('change', onDatabaseChange);
return _data;
});
} else {
return $q.when(_data);
}
}
This code works without using crypto-pouch well, but if I insert the _db.crypto(...) no data is shown in my list. Can anyone help me? Thanks in advance!
I'm guessing that your put is happening before the call to crypto has finished. Remember, javascript is asynchronous. So wait for the crypto call to finish before putting your design doc. And then use a callback to access your database after it's all finished. Something like the following:
function initDB(options) {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
_db.crypto(password)
.then(function(){
// add a design document
_db.put(allTypeOne).then(function (info) {
options.success(_db);
})
.catch(function (err) { console.error(err); options.error(err)})
.catch(function (err) { console.error(err); options.error(err);})
}
}
initDB({
success:function(db){
db.query....
}
)