Pretty much I have built an application for users to receive points and every 10 points they should receive a trophy. RewardPoints are integer and Trophies is an array. I want to increment the rewardPoints when user pays and at the same time do the validation to push a trophy if existing points after the update are 10 or 20 or 30 etc. I've somehow made it using normal js without the push(simply using math.floor() to set the numoftrophies) inside the .exec() function but i have other problems occurring on user.save(). I want to transform this:
User.findById(req.body.userID).exec(function(err, user){
if (err){throw err;}
user.rewardPoints = user.rewardPoints + 1;
let trophyNumbers = Math.floor(user.rewardPoints / 10)
user.trophies = trophyNumbers;
user.save();
})
to something like this:
User.update({ _id: req.body.userID },
{
$inc: { rewardPoints: 1 },
$push: {
trophies: {
trophy: new Date(),
trophyNum: Math.floor(rewardPoints / 10)
}
}
})
.exec(function (err, res) {
if (err) { throw err; }
//trophy must be added every 10 points
console.log('points saved');
});
How do i access the existing rewardPoints inside $push of trophies? If anyone could help I'd be really appreciative.
try this:
User.findById(req.body.userID).exec(function (err, user) {
if (err) { throw err; }
let newRewardPts = user.rewardPoints + 1;
User.update({ _id: req.body.userID },
{
$inc: { rewardPoints: 1 },
$addToSet: {
trophy: new Date(),
trophyNum: Math.floor(newRewardPts / 10)
}
})
.exec(function (err, res) {
if (err) { throw err; }
//trophy must be added every 10 points
console.log('points saved');
});
})
Related
I'm trying to update collection many times in a loop but each time I get the value of oldRight not changed it gives the first value always.
I'm storing topics in mongodb using nested sets pattern.
for(let name of level1) {
console.log(name);
var parent = 'root';
getParentAndAddTopic(name, parent, function (err, topic) {
if (err) {
console.log(err);
}
var oldRight = topic.right;
console.log(oldRight);
db.topics.create({name: name, parent: 'root', left: oldRight, right: oldRight + 1}
, function (err, res) {
if (err) throw err;
});
db.topics.updateMany({right: {$gte: oldRight}}, {$inc: {right: 2}}
, function (err, res) {
if (err) throw err;
});
});
function getParentAndAddTopic(name, parent, callback) {
db.topics.find({name: 'root'}, function (err, topics) {
if (err) {
callback(err, null);
} else {
callback(null, topics[0]);
}
});
}
}
Working with the database is an asynchronous function, you can't do it in a normal loop. And change var to let, using var is a bad practice leading to many problems.
I'm trying to figure out the best way to prevent duplicate documents from being saved in MongoDB.
Right now my form takes the user_url from the user. The logic is:
Check if the user_url is valid. (dns.lookup)
If user_url is new, save it to the database and return url_ID.
If user_url is old, just return the url_ID.
I think my 2 options are:
var findOneURL = function(user_url, done) {
URL.findOne({
orig_url: user_url
}, (err, data) => {
if (err) {
done(err);
}
done(null, data);
})
}
or
var findEditThenSave = function(user_url, done) {
URL.findById(user_url, (err, data) => {
if (err) {
done(err);
}
data.save((err, data) => {
if (err) {
done(err);
}
done(null, data);
});
})
};
It's not working terribly well at the moment but this is the live version:
https://kindly-fisherman.glitch.me/
EDIT2: I think I got it working properly now. Here's my logic:
Saving to database: dns.lookup -> findByURL -> (If it doesn't exist) -> countURLs -> findAndUpdateURL -> Return what was saved to database.
OR -> (If it exists) -> Return the record.
Retrieving from database: findByID
The best choice is findOneAndUpdate query with upsert and returnNewDocument options
db.collection.findOneAndUpdate({ orig_url: user_url }, { $set: { orig_url: user_url }}, { upsert: true, returnNewDocument: true })
In mongoose
URL.findOneAndUpdate({orig_url: user_url }, { $set: { orig_url: user_url }}, { upsert: true, new: true }, (err, data) => {
if (err) {
done(err);
}
// data will contain your document
done(null, data);
});
upsert option specifies whether to insert document if not found, new (returnNewDocument in mongo's console) - whether to return old or updated document - if false (default is false) you will have null for inserted documents.
Instead of using
db.insert()
you should use
db.update()
and specify
$upsert: true
[here]
I have a node.js app where I want to send data from mongoDB over socket.io where I can have the data display on a client but I can't figure out how to send it over the socket, the code is as follow
MongoClient.connect("mongodb://localhost:27017/", function (err, db) {
if (err) throw err;
var dbo = db.db("database1");
dbo.collection("items").find({
iname: search,
qty: qValue
}, {
_id: 0
}).toArray(function (err, result) {
if (err) throw err;
if ({ $eq: "yesView"}) {
console.log("Find Succsessful;");
if ({ $eq: "notRec"}) {
socket.emit('findSuccess', (result[2]), (result[3]))
}
But on the client when i have
socket.on('findSuccess', function (view, rec) {
viewVal = view;
recVal = rec;
});
both viewVal and recVal are equal to null and when I do console.log(result); if i put in cd for the search and 4 for the qValue it has
[ { iname: 'cd',
qty: '4',
view: 'yesView',
rec: 'notRec' } ]
My question how do i get viewVal on client to equal what view is in the document?
As #gaetanoM said, it works if you change result[2] to result[0].view, I'm only answering this because I don't want to leave it unanswered.
I have a problem. I renamed my collection responses into old. It works really well but now I need to retrieve my data and my impediment is that I only used the model to retrieve my data from a collection. But now I need to retrieve my data from my renamed collection but I have no model and schema. I tried to create a schema and a model but it didn't work. It returns no elements.
Here is a part of the code :
app.get("/Play", function(req, res) {
var urlTempBox = 'http://localhost:3000/Play';
///////////////////////////////////////////////////////////
request(urlTempBox, function(error, response, body) {
if (error) {
throw (error);
} else {
var jobj = JSON.parse(response.body);
persistRS(jobj);
setTimeout(function() {
ResponseDatabase.find()
.populate('unitCode')
.exec(function(err, finalData) {
if (err) throw (err);
mongoose.connection.db.listCollections({
name: 'old'
})
.next(function(err, collinfo) {
if (err) throw (err);
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
} else {
console.log('fk');
res.send(finalData);
}
})
})
}, 5000);
}
});
Here is the part where it doesn't work: console.log(oldData) returns nothing. And I know that my data is in the database when I try to retrieve them.
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
}
Finally I found how to do maybe it will be usefull for someone
You just need in your schema to precise the name of your collection like this
( collection : 'old' )
var nameSchemaOldRS = new mongoose.Schema({
MainClass: String,
BookingClass: String,
carID: String,
unitCode:{type: String, ref: 'Map' ,required: [true,'No post id found']},
Deck:Number,
Orientation:String,
Position:String,
}, {
versionKey: false,
collection : 'old'
},);
I am using nodeJS and mongodb in one of my project.
I am trying to save data in multiple collection in one save button.
The code which I am using to achieve this is as follow:
var lastInsertId;
loginData={
userName: req.body.txtUsername,
password: req.body.txtPassword,
active:1,
createdOn:new Date(),
updatedOn:new Date()
};
var dbo = db.db("test");
dbo.collection("login").insertOne(loginData, function(err, result) {
if (err) throw err;
lastInsertId=result.insertedId;
});
if(lastInsertId){
usersData={
email: req.body.txtEmail,
firstName: req.body.txtFirstName,
lastName:req.body.txtLastName,
mobileNumber:req.body.txtMobileNumber,
login_id:lastInsertId,
active:1,
createdOn:new Date(),
updatedOn:new Date()
};
dbo.collection("users").insertOne(usersData, function(err, result) {
if (err) throw err;
console.log('saved to users');
});
}
Could you please tell what is wrong in the above code?
Thank you.
Regards,
Saloni
I want to give an explanation regarding the above issue with the code.
var lastInsertId; //it is undefined right now
//The following function is an asynchronous function.
var dbo = db.db("test");
dbo.collection("login").insertOne(loginData, function(err, result) {
if (err) throw err;
lastInsertId=result.insertedId;
});
/*NodeJs doesn't run synchronously. So, while it is running
above function i.e. insertOne, without it being completed it
reaches here.
Since, the above function is not completed
executing, lastInsertId will be undefined still.
So, the following block of code doesn't run */
if(lastInsertId){ //this block won't run
usersData={
//key-value pairs
};
dbo.collection("users").insertOne(usersData, function(err, result) {
if (err) throw err;
console.log('saved to users');
});
}
/*The solution to the above problem can be achieved by putting the
code block inside 'if(lastInsertId)' in callback of insert login.
So it would run only after the execution of insertOne function.*/
//Therefore the correct code would be:
var dbo = db.db("test");
dbo.collection("login").insertOne(loginData, function(err, result) {
if (err) throw err;
lastInsertId=result.insertedId;
if(lastInsertId){ //this block will run
usersData={
//key-value pairs
};
dbo.collection("users").insertOne(usersData, function(err, result) {
if (err) throw err;
console.log('saved to users');
});
}
});
I think move IF block inside callback of insert login function like this should work
var lastInsertId;
loginData = {
userName: req.body.txtUsername,
password: req.body.txtPassword,
active: 1,
createdOn: new Date(),
updatedOn: new Date()
};
var dbo = db.db("test");
dbo.collection("login").insertOne(loginData, function (err, result) {
if (err) throw err;
lastInsertId = result.insertedId;
if (lastInsertId) {
usersData = {
email: req.body.txtEmail,
firstName: req.body.txtFirstName,
lastName: req.body.txtLastName,
mobileNumber: req.body.txtMobileNumber,
login_id: lastInsertId,
active: 1,
createdOn: new Date(),
updatedOn: new Date()
};
dbo.collection("users").insertOne(usersData, function (err, result) {
if (err) throw err;
console.log('saved to users');
});
}
});