So I am trying to update the value of an object inside an array inside a document. The Schema for the document looks like this:
var pollSchema = new Schema({
title: String,
hash: String,
answers: [{answer: String, votes: Number}]
});
And this is how my current update code looks like:
module.exports.updatePoll = function(socket, data){
var answerss = 'answers.0.votes';
hash = data.url.match(/\/([^/]*)$/)[1];
Poll.findOne({'hash' : hash}, function(err, poll){
if (err) return handleError(err);
console.log(poll.answers[data.id])
});
Poll.update({hash: hash}, {$inc: {'answers.{data.id}.votes': 1}}, function(err, poll){
if (err) return console.log(err);
//socket.emit('updatePoll', hash);
});
Ive tried pasting answerss in it instead of 'answers.{data.id}.votes'and also tried some other things. It only really works when I directly paste in 'answers.0.votes'. And this is a problem because the data.id can be a value of 0 to 10. I have no idea how I would implement this and the other answers on stackoverflow or google did not give much insight on the problem.
I hope you can help me. Thanks!
You don't need the initial find from what I can tell. You can do it all in one update statement. You need to match the array element you want to update simply by specifying its index:
var answerKey = 'answers.' + data.id + '.votes';
var updateJSON = {$inc: {}};
updateJSON.$inc[answerKey] = 1;
hash = data.url.match(/\/([^/]*)$/)[1];
Poll.update({hash: hash}, updateJSON, function(err, poll){
if (err) return console.log(err);
//socket.emit('updatePoll', hash);
});
Related
lets say each post in my posts array has two properties name and number. so its something like
var posts = [{name:"hey", number: 1}, {name:"foo", number:"2"}]
Javascript allows me to change these properties in foreach loop like this:
posts.forEach(function(post){
post.name = "bar"
});
and my array becomes:
var posts = [{name:"bar", number: 1}, {name:"bar", number:"2"}]
but it doesnt allow me add a new property like:
posts.forEach(function(post){
post.adress = "bar"
});
my object stays the same. Is there a way to add properties in a foreach loop in javascipt
edit:
this is happening using mongoose inside a callback..
Post.pagination(options, function(err, posts) {
if (err) console.log(err)
posts.forEach(function(post){
post.votetype = 1;
});
console.log(posts);
res.send({ posts : posts })
})
after this votetype property is not added
The problem is that data returned from Mongoose is immutable.
The code below is untested but should give you a hint on how to make the data mutable and modify it.
The key point is calling toObject() on the Mongoose document object you wish to modify.
Post.pagination(options, function(err, posts) {
if (err) console.log(err);
var resultPosts = posts.map(function(post) {
var tmpPost = post.toObject();
// Add properties...
tmpPost.votetype = 1;
return tmpPost;
});
console.log(resultPosts);
res.send({ posts : resultPosts });
});
I have a driver.js that contains a driver schema. Also the driverController.js, which contains my rest methods. GET, POST, DELETE, and PUT.
What i would like to do is
GET - http://localhost:3000/drivers?available=true
and have it return all of the drivers that are available.
My driver schema simply looks like this:
var mongoose = require('mongoose');
var DriverSchema = new mongoose.Schema({
name: String,
available: Boolean,
latitude: Number,
longitude: Number
});
mongoose.model('Driver', DriverSchema);
module.exports = mongoose.model('Driver');
I looked at some documentation, but I haven't been able to do anything.
Here's my GET method in which I'm attempting to add parameters
// GETS ALL DRIVERS FROM THE DATABASE
router.get('/', function (req, res) {
Driver.find({}, function (err, driver) {
if (err) return res.status(500).send("There was a problem finding the drivers.");
var available = req.query.available;
if (available == driver.available )
res.status(200).send(available );
else
res.status(200).send("Nice! " + driver.available);
});
});
This comparison doesn't ever work. It always goes to the else statement. I'm not quite sure why but the output is "Nice! undefined" Even though I have plenty of drivers in my database, and if I only put inside the else statement
res.status(200).send("Nice! " + driver);
Then it gives me the list of drivers.
Nonetheless, I would like to be able to use query parameters in order to find drivers.
Any hints or tips would be greatly appreciated, as this is a project and I have never worked with restAPI, or javascript before. Thanks!
NOTE: Mongoose, express. node.js, and mongoDB are being used.
if I only put inside the else statement res.status(200).send("Nice! " + driver); Then it gives me the list of drivers.
it's a list of drivers, with if (available == driver.available ) you're comparing a boolean with an array of objects,
instead of fetching all the drivers and checking if they have availabe == true , add the condition to the .find() and return the result :
// GETS ALL DRIVERS FROM THE DATABASE
router.get('/', function (req, res) {
Driver.find({ available : req.query.available }, function (err, drivers) {
if (err) return res.status(500).send("There was a problem finding the drivers.");
res.status(200).send(drivers);
});
});
EDIT :
you can do this to add filter depending on the query string :
// GETS ALL DRIVERS FROM THE DATABASE
router.get('/', function (req, res) {
var params = {};
Object.keys(req.query).forEach((v, k) => params[k] = v);
Driver.find(params, function (err, drivers) {
if (err) return res.status(500).send("There was a problem finding the drivers.");
res.status(200).send(drivers);
});
});
having ?name=Wario&available=true will create an object like { name : 'wario', available : true and pass it to the .find()
var LINK = mongoose.model('link', {
id: mongoose.Schema.Types.ObjectId,
linkA: Boolean,
linkB: Boolean,
}, 'link')
(model for LINK - here as reference)
When using mongoose on nodeJS I can use the find() function to return all documents in a collection:
var Test = LINK.find({}, (err, user) => {
if (err) console.log("error: " + err)
else console.log("users: " + user)
}, 4000)
which returns all the data in terminal. Easy, right?
But the problems arise when I try to use a query:
var Test = LINK.find({linkA:'true'}, (err, user) => {
if (err) console.log("error: " + err)
else console.log("users: " + user)
}, 4000)
The query at first didn't return any results (even though there were documents on mongodb populated beforehand). But after adding documents to mongodb via mongoose- the documents added can be accessed, but not any of the others that were created on the mongodb console.
Is there a reason for this? I'm suspicious that I'm using the find() function wrong but it seems to work fine when the documents were added via mongoose or I use an empty query so I'm not sure.
Any help would be appreciated.
Thanks.
The problem was the way I was storing the information.
As pointed out by Amiram Korach the documents had stored boolean values with quotation marks by mistake and so mongoose was recognising it as a string value.
I am writting a little app to calculate and keep track of how much gas my car is using. But i have a problem with my facade.
When i am trying to add some new details to my database, i only get a empty object somehow.
I know the problem is in my facade, and maybe some of you can see what it is.
(Don't worry about the name of the method)
function addTitle (kilometer, liter, kmLiter, callback){
var data = {
kilometer: kilometer,
liter: liter,
kmLiter: kmLiter
}
detail.create({details:data}, function(err, result){
if(err)
return callback(err);
else
callback(null, result);
});
};
And this is the model of the DB
var DetailSchema = mongoose.Schema({
details:[{
kilometer: String,
liter: String,
kmLiter: String}
]
});
mongoose.model('Details', DetailSchema, "details");
Anybody that can find the error?
Assuming your schema definition of details being an array is what you want, you need to also make details an array when you create new docs.
So your function should change to:
function addTitle (kilometer, liter, kmLiter, callback){
var data = {
kilometer: kilometer,
liter: liter,
kmLiter: kmLiter
}
detail.create({details: [data]}, callback);
}
lets say each post in my posts array has two properties name and number. so its something like
var posts = [{name:"hey", number: 1}, {name:"foo", number:"2"}]
Javascript allows me to change these properties in foreach loop like this:
posts.forEach(function(post){
post.name = "bar"
});
and my array becomes:
var posts = [{name:"bar", number: 1}, {name:"bar", number:"2"}]
but it doesnt allow me add a new property like:
posts.forEach(function(post){
post.adress = "bar"
});
my object stays the same. Is there a way to add properties in a foreach loop in javascipt
edit:
this is happening using mongoose inside a callback..
Post.pagination(options, function(err, posts) {
if (err) console.log(err)
posts.forEach(function(post){
post.votetype = 1;
});
console.log(posts);
res.send({ posts : posts })
})
after this votetype property is not added
The problem is that data returned from Mongoose is immutable.
The code below is untested but should give you a hint on how to make the data mutable and modify it.
The key point is calling toObject() on the Mongoose document object you wish to modify.
Post.pagination(options, function(err, posts) {
if (err) console.log(err);
var resultPosts = posts.map(function(post) {
var tmpPost = post.toObject();
// Add properties...
tmpPost.votetype = 1;
return tmpPost;
});
console.log(resultPosts);
res.send({ posts : resultPosts });
});