Mongoose update query not working with node.js - node.js

First I am making entries in mongodb by:
var device = new Device(inputDetailsJson); //device model instance
device.save(function(err) {
if (err) {
res.send(err);
} else {
res.write('Successful');
res.end();
}
});
This is the device model:
// Dependencies
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// Schema Definition
var deviceSchema=new Schema ({
"deviceId":{ type : String , unique: true},
"version":{ type : String },
"manufacturer":{ type : String },
"modelname":{ type : String },
});
// Model
module.exports = mongoose.model('de', deviceSchema);
This is the inputDetailsJson:
{
"deviceId":"3236172417",
"version":"5.2.3",
"manufacturer":"abc",
"modelname":"example"
}
These details are getting entered correctly, but when I try to update something, it reflects no changes.
var device=new Device();
device.update({deviceId:"3236172417"},{modelname:"test"}
,function(err) {
if (err) {
return console.error(err);
}
else{
res.write('successful');
res.end();
It displays 'successful' even though no changes are made in the mongodb database.

var Device = require('your device model file');
Device.model.findOneAndUpdate({
deviceId:"3236172417",
},{$set:{modelname:"test}},function(err, user) {
});

For updating the device you don't need to create a new device, using var device=new Device();
you should simply update, same as you try to find a document.
Device.update({deviceId:"3236172417"},{modelname:"test"}
,function(err) {
if (err) {
return console.error(err);
}
else{
res.write('successful');
res.end();

Related

How to get data from mongodb for dynamically created schema model

I am trying to get data from mongodb but could not. Because below the error is the reason.I have inserted data into mongodb by dynamically creating schema model.So I am not able to get data from mongodb.How to get data from mongodb for (dynamically creating schema) collection? Please help anyone.I have searched in google but no use.
MissingSchemaError: Schema hasn't been registered for model "Tea".
Use mongoose.model(name, schema) at Mongoose.model
createschema.js
const db = mongoose.createConnection(
"mongodb://localhost:27017/products", {
useNewUrlParser: true,
useUnifiedTopology: true
}
);
function dynamicModel(suffix) {
var collsName = suffix.charAt(0).toUpperCase() + suffix.slice(1);
var collsSmall = suffix.toLowerCase();
var newSchema = new Schema({
pid: {
type: String
},
product_name: {
type: String
},
product_price: {
type: Number
}
}, {
versionKey: false,
collection: collsSmall
});
try {
if (db.model(collsName)) return db.model(collsName);
} catch (e) {
if (e.name === 'MissingSchemaError') {
return db.model(collsName, newSchema, collsSmall);
}
}
}
module.exports = dynamicModel;
data.controller.js:
const mongoose = require('mongoose');
module.exports.getCollectionData = (req, res, next) => {
let collection = req.query.collection;
let tabledata = mongoose.model(collection); //Got MissingSchemaError
tabledata.find({}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
res.json({ data: docs, success: true, msg: 'Products data loaded.' });
}
})
}
//Create model
module.exports.newCollection = (req, res, next) => {
var collectionName = req.query.collectionName;
var NewModel = require(path.resolve('./models/createschema.model.js'))(collectionName);
NewModel.create({ }, function(err, doc) {});
}
db.js:
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI, (err) => {
if (!err) { console.log('MongoDB connection succeeded.'); } else { console.log('Error in MongoDB connection : ' + JSON.stringify(err, undefined, 2)); }
});
require('./createschema.model');
api call:
http://localhost:3000/api/getCollectionData?collection='Tea'
Try db.model instead of mongoose.model in function getCollectionData
Since you created the collection on that particular connection, you have to use the same connection to get the model as well.
const db = mongoose.createConnection(
"mongodb://localhost:27017/products", {
useNewUrlParser: true,
useUnifiedTopology: true
}
);
module.exports.getCollectionData = (req, res, next) => {
let collection = req.query.collection;
let tabledata = db.model(collection); //Change here
tabledata.find({}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
res.json({ data: docs, success: true, msg: 'Products data loaded.' });
}
})
}
You fundamentally misuse mongoose.model() / connection.model().
This function can ONLY be used to CREATE a NEW mongoose model using
required model name and schema deffinition parameters.
In createschema.js when you have try {if (db.model(collsName))
return db.model(collsName);} catch you are NOT checking if model
already exists. db.model(collsName) will always throw an error
because you are not providing second required parameter with schema
definition.
I presume you are trying to check if model already exists and if so
return it. Please see documentation for
Connection.prototype.models. the fragment above should
therefore be:
try {
// db is an instance of mongoose.Connection
let existingModel = db.models[collsName];
if (existingModel) return existingModel;
} catch
Likewise in data.controller.js getCollectionData currently you are
calling a method to create a new mongoose model 'mongoose.model()',
but don't provide a schema (hence why you get MissingSchemaError)
you need to EITHER
get the model from mongoose instance (if already registered as you seem to imply)
let tabledata = mongoose.connection.models[collection];
OR
create a new mongoose model
const dynamicModel = require('./createschema.js');
let tabledata =
dynamicModel(collection)

deleting route for an array in mongodB using node.js

var userSchema=new mongoose.Schema({
username:String,
password:String,
email:String,
tasks:[{
task: String
}]
});
This is my database schema.I want to create a delete route for the task to be removed.Can anyone tell me how to do so. Right now I am able to fetch the task id.
Here is link to my c9 project https://ide.c9.io/akspan12/newprojectworkspace
var express = require('express');
var router = express();
//I will take static values you can give dynamic values by using req.body
router.post('/Delete_User_Task',function(req,res){
var UserSchema = require('/path/to/Schema.js');//your schema model path
var username = 'akshansh123'; //assume it is present in db
//If you want to remove all task of this user and set one task as empty string your query and changes will be like below
var query = {
'username' :username
};
var changes = {
$set:{
'tasks':[{
task:''
}]
}
};
//If you completely want to remove json array tasks from user document than your query and changes will be like below
var query = {
'username' :username
};
var changes = {
$unset:{
'tasks':''
}
};
//If you want to remove particular task suppose say sleeping from user document than your query and changes will be like below
var query = {
'username' :username
};
var changes = {
$pull:{
'tasks':{
'task':'sleeping'
}
}
};
//If you want to remove selected tasks suppose say sleeping,walking,drinking from user document than your query and changes will be like below
var query = {
'username' :username
};
var changes = {
$pull:{
'tasks':{
'task':{
$in:['sleeping','walking','drinking']
}
}
}
};
UserSchema.update(query,changes,function(err,Result){
if(!err){
res.send('Successfully Removed tasks');
}else{
res.send('something went wrong');
console.log(err);
}
})
})
Hope this may solve your issue!!!
app.patch("/todo/:id",function(req,res){
User
.findById(req.user.id, function(err, foundUser) {
if(err){
req.flash("error",err.message);
console.log(err);
return res.redirect("back");
} if(!foundUser) {
req.flash("error","User not found");
return res.redirect("back");
} else {
foundUser.update({$pull: {tasks: {_id: req.params.id}}}, function(err) {
if(err) {
req.flash("error",err.message);
console.log(err);
return res.redirect("back");
} else {
req.flash("success","Task removed");
return res.redirect("/todo");
}
});
}
});
});
This is the delete route I used.

How to check if that data already exist in the database before save

Hey guys I have a question, how to do validations before saving the edited or posted (post or put action ) data in mongoose !?
for Example, if action already exist in the database, the user will receive a some sort of error. I try this but not working :
1-NOT WORK
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var actionSchema = new Schema({
action: {
type: String,
required: true,
},
});
var data = mongoose.model('Action', actionSchema);
actionSchema.pre('save', function (next) { // Middlware to verify if action already existe
var self = this;
data.find({
action: self.action
}, function (err, actions) {
if (!actions.length) {
next();
} else {
console.log('action exists: ', self.name);
next(new Error("Action exists!"));
}
});
});
module.exports = mongoose.model('Action', actionSchema);
2 --- NOT WORK SECOND METHODE : ------------------------------------
var data = mongoose.model('Action', actionSchema);
actionSchema.pre('save', function (next) {
data.count({
action: this.action
}, function (err, count) {
if (count == 1) {
console.log('action exists: ', this.action);
next(new Error("Action exists!"));
//already exists
} else {
next();
//do the action
}
});
});
3- WORKING ALTERNATIVE -- NODE JS CONTROLLER ----I found this trick (work good) that is to do a check before the update (check)
But I would like to know if there is possibility to do it before my save in my model MONGOOSE !?
// router.put('/actions/:action_id');
Action.findById(req.params.action_id, function (err, upaction) {
if (err) { //no action id in database match with params.action_id
res.send(err);
} else { // find == true
// chek if action name existe
Action.findOne({
'action': req.body.action
})
.exec(function (err, found_action) {
if (err) { // ereur bizare sest produite
next(err);
}
if (found_action) { // name action exist
res.send('name action existe');
}
else { // name action no exist
upaction.action = req.body.action;
upaction.save(function (err, acti) {
if (err) {
res.send('error on save');
}
res.send(upaction); // send a document
});
}
});
}
});
Check whether the data already avaliable and then perform the action you want
var data = mongoose.model('data', actionSchema);
data.count({action: this.action}, function(err, count) {
if(count == 1){
//already exists
}
else{
actionSchema.pre('save', function (next) {
});
}
});
I don't understand why are you doing too many operation to do a single operation. Mongodb provides update function which has ability to check and insert. If you want a document to be inserted only when some condition comes true or false. update can do that in a singly query. Here you go.
Action.update({ action:{ $eq:req.body.action }},{ $setOnInsert: new_action }, { upsert: true }, function(err, res){
if(!err && !!res.upserted){
// no document was found hence inserted
}else if(!err && !res.upserted){
// already existing
}else{
// something wicked happend
}
})
Here you need to pay attention that new_action must not be a instance of your mongoose model rather it should be simple object/document which you want to insert.

Mongodb schema defining

Coding a news/media website, I want a "News" section, "Reviews" section, a
"Trending" section, which combines both the previous sections, just like here:
I have made one schema for "News", one for "Reviews".How can I make a "Trending" section(as in the image above "Movies" section)?
Code :
In app.js,
//LANDING PAGE
app.get('/', function (req, res,next) {
Blogdemo.find({}).sort([['_id', -1]]).limit(3).exec(function(err,allBlogs) { //finds latest posts for 1st Schema (upto 3)
if(err) {
console.log(err);
next();
} else {
res.locals.blog = allBlogs;
// res.render("landing", {blog : allBlogs , moment : now});
next();
}
})
}, function (req, res) {
Review.find({}).sort([['_id', -1]]).limit(3).exec(function(err,allReviews) { //finds latest posts of 2nd Schema
if(err) {
console.log(err);
} else {
res.locals.review = allReviews;
res.render("landing", res.locals);
}
})
})
In review.js ,
var mongoose = require("mongoose");
//SCHEMA SETUP
var reviewSchema = new mongoose.Schema({
image : String,
title : String,
body : String,
rating : String,
created : {type : Date, default : Date.now()},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment" //name of the model
}
]
})
module.exports = mongoose.model("review", reviewSchema);
The "News" schema is almost the same(no review).
Is my way of defining schema wrong? If not, then how can I build the "Trending" section?
Is there any mongodb method which can find the latest posts from "News" and "Reviews" to build the "Trending" section(just like in 1st picture)?
From what i can see from your code, your current News and Review Schema looks fine.
You need to define another Schema for Trending.
var TrendingSchema = new mongoose.Schema({
referenceId : {
type : mongoose.Schema.Types.ObjectId
},
postType : String //To store News or Reviews
});
While saving new News or Reviews, insert the _id of newly saved document in the trending collection.
var news = new News();
news.image = newsImage;
...
news.save(function(err,result)
{
if(!err)
{
var trending = new Trending();
trending.referenceId = result._id;
trending.postType = "News";
treding.save(function(err)
{
if(!err)
{
//success response
}
else
{
//error response
}
});
}
else
{
//send error response
}
});
Similarly while saving Review Post
var review = new Review();
review.image = reviewImage;
...
review.save(function(err,result)
{
if(!err)
{
var trending = new Trending();
trending.referenceId = result._id;
trending.postType = "review"
treding.save(function(err)
{
if(!err)
{
//success response
}
else
{
//error response
}
});
}
else
{
//send error response
}
});
Thus now Trending Collection will contain, newly saved News or Review, in the order they are created. Thus you will be able to get new Review or News Post.
While fetching Trending, you can populate them using News or Review Schema based on the postType.
Trendign.find({}).limit(10).exec(function(err,result)
{
if(!err && result.length!=0)
{
var trendingPosts = [];
result.forEach(function(trending){
if(trending.postType === "News"){
trending.populate({path : 'referenceId',model : 'News'},function(err,populatedItem)
{
if(!err)
{
trendingPosts.push(populatedItem);
}
});
}
else if(trending.postType === "Review"){
trending.populate({path : 'referenceId',model : 'Review'},function(err,populatedItem)
{
if(!err)
{
trendingPosts.push(populatedItem);
}
});
}
});
//now send the trendingPost array with latest News and Review Posts
}
else
{
//send Error response
}
});
Now you can show the latest News or Review and write the type postType.
Hope this is what you want.

Return partial documents from Node API querying Mongo

I have a Node API that is querying my Mongo database.
I'm able to return all documents within a collection. Now, I want to return partial documents.
My model (i.e. Player.js) looks like this:
var mongoose = require('mongoose');
// Create schema for players
var playerSchema = mongoose.Schema(
{
player_name:String,
goals:Number,
clubs:
{
club_name:String,
season:String
}
}
);
var Player = module.exports = mongoose.model('Player',playerSchema);
// get all players
module.exports.getPlayers = function(callback, limit){
Player.find(callback).limit(limit);
};
My application looks like this:
//...
app.get('/api/players',function(req,res){
Player.getPlayers(function(err,players){
if(err){
throw err;
}
res.json(players);
});
});
//...
I'd like to query all documents within my players collection but return only player_name when I go to ".../api/players/player_names"
I thought adding the code below would work but it doesn't...
This on my model:
// [previous code]
// get all player names
module.exports.getPlayerNames = function(callback,limit){
Player.find(callback,player_name:1).limit(limit)
}
This on my app.js:
//...
app.get('api/players/player_names',function(req,res){
Player.getPlayerNames(function(err,players){
if(err){
throw err;
}
res.json(players);
});
});
//...
You'll probably want something that looks like this:
var mongoose = require('mongoose');
// Create schema for players
var playerSchema = mongoose.Schema(
{
player_name:String,
goals:Number,
clubs:
{
club_name:String,
season:String
}
}
);
//Its most common to pass the callback last, as this is what others do
playerSchema.statics.getPlayers = function(limit, callback){
this.find({})
.select('player_name')
.limit(limit)
.exec(callback);
};
module.exports = mongoose.model('Player',playerSchema);
Which will return results like [{_id: ObjectId, player_name: "player1"}, ...].
If you want to return just an array of player names:
var mongoose = require('mongoose');
// Create schema for players
var playerSchema = mongoose.Schema(
{
player_name:String,
goals:Number,
clubs:
{
club_name:String,
season:String
}
}
);
//Its most common to pass the callback last, as this is what others do
playerSchema.statics.getPlayers = function(limit, callback){
this.find({})
.select('player_name')
.limit(limit)
.exec(function(err, docs) {
if(err) return callback(err); //first argument should be reserved for passing any errors
callback(null, docs.map(function(doc) {
return doc.player_name;
});
});
};
module.exports = mongoose.model('Player',playerSchema);

Resources