Model.findOne() is returning null - javascript

Model.findOne() is returning null even if the valid collection is present in the respective Model
app.post("/fleetManagement", (req, res) => {
const requestedDriverID = req.body.driverId;
console.log(requestedDriverID);
Driver.findOne({
_id: requestedDriverID
}, function(err, requestedDriverResult) {
console.log(requestedDriverResult);
res.render("fleetManagement", {
reqDriver: requestedDriverResult
});
});
})
Output
Collection in Driver Model
Check out the Output and Collection of Driver Model

Try convert requestedDriverID to ObjectId(requestedDriverID)

You need to convert the _id input to ObjectId.
Here's the updated code for your reference:
app.post("/fleetManagement",(req, res)=>{
const requestedDriverID = req.body.driverId;
console.log( requestedDriverID);
Driver.findOne({_id: ObjectId(requestedDriverID) }, function(err, requestedDriverResult){
console.log(requestedDriverResult);
res.render("fleetManagement", {
reqDriver:requestedDriverResult
});
});
})

Related

Model.create() from Mongoose doesn´t save the Documents in my Collection

I have created a sigle app with a Schema and a Model to create a Collection and insert some Documents.
I have my todoModel.js file:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const todoSchema = new Schema({
username: String,
todo: String,
isDone: Boolean,
hasAttachment: Boolean
});
const Todos = mongoose.model("Todo", todoSchema);
module.exports = Todos;
Then I have created a setUpController.js file with a sample of my Documents. Then I create a Model and I pass my sample of Documents and my Schema. I create a response to send tje result in JSON.
Everything good here, as I get the result in json when accessing to the route.
Here is the code:
Todos.create(sampleTodos, (err, results) => {
if (!err) {
console.log("setupTodos sample CREATED!")
res.send(results);
}
else {
console.log(`Could not create the setupTodos Database sample, err: ${err}`);
}
});
My problem is that this Documents don´t get saved in the collection !! When I access to the database, nothing is there.
This is my app.js file:
mongoose.connect("mongodb://localhost:27017/nodeTodo")
.then(connection => {
app.listen(port);
})
.catch(err => {
console.log(`Could not establish Connection with err: ${err}`);
});
Could anyone help me please ?
Thank you
Try creating an instance and making the respective function call of that instance. In your case, save the document after creating an instance and it works like a charm.
const newTodos = new Todos({
username: "username",
todo: "todos",
isDone: false,
hasAttachment: flase
});
const createdTodo = newTodos.save((err, todo) => {
if(err) {
throw(err);
}
else {
//do your staff
}
})
after the collection is created you can use the function inserMany to insert also a single document the function receives an array of objects and automatically saves it to the given collection
example:
Pet = new mongoose.model("pet",schemas.petSchema)
Pet.insetMany([
{
//your document
}])
it will save only one hardcoded document
I hope it was helpful

How can i update nested data by using mongoose findByIdAndUpdate

i can not able to update nested data in my mongodb. here is my "update" module at back-end side.
exports.updateOne = (req, res) => {
if (!req.body) {
return res.status(400).send({
message: "Data to update can not be empty!"
});
}
const {id} = req.params;
console.log(req.body);
User.findByIdAndUpdate(id, req.body, { useFindAndModify: false, new: true}).populate('basic')
.then(data => {
if (!data) {
res.status(404).send({
message: `Cannot update User with id=${id}. Maybe User was not found!`
});
} else
res.send({ message: "User was dupdated successfully." , data});
})
.catch(err => {
res.status(500).send({
message:
err.message || "Error updating User with id=" + id
});
});
};
and my front-end side is;
onChangePosition(e) {
const position = e.target.value;
this.setState(prevState => ({
currentStaff: {
...prevState.currentStaff,
basic:
{
...prevState.currentStaff.basic,
position:position
}
}
}));
}
onChangeEmail(e) {
const emailBusiness = e.target.value;
this.setState(prevState => ({
currentStaff: {
...prevState.currentStaff,
emailBusiness:emailBusiness
}
}));
}
updateStaff() {
StaffDataService.updateOne(
this.state.currentStaff.id,
this.state.currentStaff
).then(response => {
console.log(response.data);
})
.catch(e => {
console.log(e);
})
}
i can change state properly, and my sending data "req.body" is what i want (it is an object). There is no problem.
as you see above, i can update "email" because it is on the main body of object, but can not update "position" (nested element) because it is inside of basic (populated data).
i tried different methods by mongoose, and tried "$set" command.
Can anyone solve this?
To update, the nested value/object in your document, you should use dot notations, so it depends from the req.body variable value.
req.body shouldn't be a Mongoose doc. In such case you mongoose.toObject.
Second thing is:
[update] Object should be: field_with_subdocument.key_value: updated_propery
like this:
/** Example doc */
{
_id: 1,
parent_field: {
baby_field: value
}
}
/** Inside async function */
...await Model.findByIdAndUpdate(id, { "parent_field.baby_field": value })
Also, take a look at [`{overwrite: true}`](https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate) option. It might be useful to you.
I faced the same issue, In my case, the defined mongoose schema for that model did not match the nested Object I was passing to the findByIdAndUpdate method. let me simplify it, here is the model
import { model, Schema } from 'mongooose';
const UserModel = model('user', new Schema({
profile: {
avatar: String,
bio: String,
}
}));
And here is the update query:
async function getDefaultProfile() {
const user = await UserModel.findById(process.env.DEFAULT_USER);
return user.profile;
}
const profile = await getDefaultProfile();
UserModel.findByIdAndUpdate('user id', {
$set: {
profile: profile
}
});
The important note was that my getDefaultProfile function returns a mongoose nested object, not a pure object. So in the returned object, I had $set, $get, etc function. So as you know this object is not what we define in the mongoose model, therefore the mongoose ignores it.
So I guess you have the same problem, or something close to my issue.
What should I do?
Run your project in debugging mode.
then check req.body or whatever that gives you the nested object (in my case getDefaultProfile).
Check it with your model, Are they equal?
And if that solution does not work for you, please try this solution, write a utility function:
export async function flatObjectAndSeparateThemByDot(
object: any,
): Promise<any> {
const res: any = {};
(function recurse(obj: any, current?: string) {
for (const key in obj) {
const value = obj[key];
// joined keys with dot
const newKey = current ? current + '.' + key : key;
if (value && typeof value === 'object') {
// it's a nested object, so do it again
recurse(value, newKey);
} else {
// it's not an object, so set the property
res[newKey] = value;
}
}
})(object);
return res;
}
then you can pass your nested object to this function and you will get something like this: { "profile.avatar": "lorem ipsum", "profile.bio": "bio temp" }. So to show you how this function works I will write a sample code:
const sampleProfile = {
profile: {
avatar: "asd",
bio: "sample"
}
}
const profile = await flatObjectAndSeparateThemByDot(sampleProfile);
await UserModel.findByIdAndUpdate('user id', {
$set: {
// other fields,
...profile
}
});

Express and Mongoose-failing to update an object

I'm trying to update an object by assigning it a new field, which is defined in the schema, like this:
exports.updatePlot = async (req, res) => {
let modifications = {};
modifications = Object.assign(modifications, req.body.props);
const id = modifications.id;
try {
const updatedPlot = await Plot.findByIdAndUpdate(
id,
{ $set: modifications },
{ new: true }
);
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 works when I modify existing fields. However, when I try to add a new field (which is defined in the Mongoose schema, but does not exist in the object in the database), it fails. Meaning, there is no error, but the new field is not added.
Any ideas?
According to mongoose documentation of findByIdAndUpdate
new: bool - true to return the modified document rather than the original. defaults to false
upsert: bool - creates the object if it doesn't exist. defaults to false.
You are mistaking new with upsert
Moreover as #Rahul Sharma said and looking at mongoose documentation example, you do not need to use $set

How can i save results from mongoose query to a variable

I'm trying to save some objects into an array by looping through a list of songs in an album, looking for relevant songs and trying to save into array for later use. is there any way to achieve this?
I need some explanation using mongoose.
exports.playlistPlayer = function (req, res, next) {
Playlist.findById({
_id: req.body.playlist._id
}, (err, playlist) => {
var customAlbum = []; //This variable it's inside the same block i believe
playlist.songs.forEach(function (song) {
Song.findById({
_id: song.song_id
}, (err, songs) => {
var customSong = {
title: songs.title,
time: songs.time,
source: songs.source,
song_id: songs._id
}
customAlbum.push(customSong)
console.log(customAlbum) //it works here
});
});
console.log(customAlbum) //it returns an empty array here where i need the data
});
};
The problem is that the findById method is also asynchronous. I recommend you to learn about promises in javascript. One possible solution would be using the async/await feature from ES7:
// asynchronous function
exports.playlistPlayer = async (req, res, next) => {
// wait for the findById method promise to resolve
const playlist = await Playlist.findById({
_id: req.body.playlist._id
})
// wait for finding all songs in db whose id's are in
// the playlist.songs array
const songs = await Song.find({
_id: { $in: playlist.songs }
})
// create the customAlbum by using the map method to
// tramsform the song objects to the required form
const customAlbum = songs.map(song => ({
title: song.title,
time: song.time,
source: song.source,
song_id: song._id
}))
// and there you should now have your customAlbum array
console.log(customAlbum)
// now you can use it for example
// to return a response to the client:
// res.json(customAlbum)
}

append object in javascript

In below my code, I try to append the populate in mainQuery object. If I pass only types, then I get the expected result and query also build. If I pass both types and sub category, then query was broken and object is not added as per expected query bellow. Kindly give solution for this ?
mainQuery = Category.find();
if(req.param('types')) {
searchKey = "types";
typesObj.where = {
id: 1
};
mainQuery.populate(searchKey, typesObj);
}
if(req.param('subcat')) {
searchkeySubCat = "subcategory";
typesSubcat.where = {
id: 1
};
mainQuery.populate(searchkeySubCat, typesSubcat);
}
mainQuery.exec(function (err, category) {
});
Expected Query as below
Category.find().populate('types', {where: {id:1}}).populate('subcategory', {where: {id:1}}).exec(function (err, res) {
console.log(res)
})
Try as below:
function _getWhereClause(key, value) {
return {where: {key: value}};
}
if (req.param('types')) {
populateKey = 'types';
mainQuery.populate(populateKey, _getWhereClause('id', 1));
}
// Do the same for any number of populate you want
At last execute the query:
mainQuery.exec(function (err, category) {
});
Check the documentation for more understanding- http://sailsjs.org/documentation/reference/waterline-orm/queries/populate
What are you tryin to is basically method chaining with mainQuery object . So basically you are forming one query and later on use that query . I will suggest that you make this query as a string .
for eg.
mainQuery = "Category.find().";
mainQuery+= "populate("+searchKey+","+ typesObj+").";
mainQuery +="populate("+searchkeySubCat+","+ typesSubcat+").";
mainQuery +="exec(function (err, res) { console.log(res)});";
So when you will access mainQuery you will have :
Category.find().populate('types', {where: {id:1}}).populate('subcategory', {where: {id:1}}).exec(function (err, res) {
console.log(res)
});

Categories

Resources