MongoDB: $push into an array based on a variable's contents - javascript

I'm trying to $push an item into my record in MongoDB built on Node (using MongoJS), like so:
exports.saveToUser = function (req, res) {
console.log("IN");
var user = req.params.user;
var param = req.params.param; // equals "foo"
var value = req.params.value; // equals "bar"
console.log("Saving Data to User");
console.log(util.inspect(param, false, null));
db.users.update({"_id": ObjectId(user)}, {$push: {param:value}}, function (err, record) {
if (err) {
console.log("Lookup Error: " + err);
} else{
console.log("Updated " + user + " with " + param);
}
});
};
This works, except the function is pushing "param: bar" instead of "foo: bar" to my record (see comments above for what this refers to).
I've tried doing $push: {eval(param):value} which was a bit of a shot in the dark but didn't work anyway. What's the best way to make this happen?

var ob = {};
ob[param] = value;
db.users.update({"_id": ObjectId(user)}, { $push: ob }, function (err, record) {
// etc..
});

Related

Node js , cannot retrive data from sqlight3 table

async function get_info(compName) {
let company = {
name:""
, activityNumber:""
, siret :""
, adresse :""
, tva :""
, logo:0
};
buff = await db.all("SELECT * FROM company WHERE name = ?", [compName], (err, rows) => {
if (err) {
console.log(err)
return err;
}
rows.forEach(element => {
console.log(element.name) // WORK
company.name = element.name;
company.activityNumber = element.activityNumber;
company.adresse = element.adresse;
company.logo = element.logo;
company.siret = element.siret;
company.tva = element.tva;
});
});
console.log(" ... " + company.name) // DOSENT WORK
return company;
}
I'm trying to get company fill and get data out of my database.
The first console.log() is good but not the second one, it's empty, and the object it returns have defaults values, there will be only one element who will match "WHERE name = ?" so I don't worry about erasing the value.

How to scan dynamoDB in lambda?

so I have a table of 10 items, each item has about 5 keys (name,experience,level, etc). Now, I want to scan that table, get each item as an object and add it to an array and then JSON stringify that array and return it.
I just need help with the scanning code and getting all items and putting it into an array.
Here's my code I have currently.
var dynamodb = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event, context, callback)
{
var returnArray = {
"cards": {}
}
getCards();
function getCards() {//Not sure how to write this function
var params = {
TableName : "toBeApprovedTable",
Key: {//not sure what to put here, since I want all items, and not searching through keys.
},
};
dynamodb.scan(params,function(err,data)
{
if(err)
{
console.log("error in scanning");
}
else
{
console.log("scanning success!");
//Not sure what to do here.
}
});
}
};
I figured it out after scrapping through Google + AWS docs.
Here is how to scan a table for all elements in the table. My return is a map, which contains an array of elements. Each element is a map of my object.
exports.handler = function(event, context, callback)
{
var returnArray = {
"cardsToBeApproved":[]
};
getCards();
function getCards() {//Not sure how to write this function
var params = {
TableName : "toBeApprovedTable"
};
dynamodb.scan(params,onScan);
}
function onScan(err,data)
{
if(err)
{
console.log("unable to scan table");
}
else
{
console.log("scan succeeded");
data.Items.forEach(function(card)
{
console.log("my card name is " + card.name);
var cardStringified = JSON.stringify(card);
returnArray.cards.push(card);
});
callback(null,JSON.stringify(returnArray));
}
}
};

Updating job status in KUE node js

I create a job:
var kue = require('kue');
var queue = kue.createQueue();
//name of the queue is myQueue
var job = queue.create('myQueue', {
from: 'process1',
type: 'testMessage',
data: {
msg: 'Hello world!'
}
}).save(function(err) {
if (err) {
console.log('Unable to save ' + err);
} else {
console.log('Job ' + job.id + ' saved to the queue.');
}
});
Is there a way I can update the job status (i.e. active, failed, in progress) myself? So for example:
The consumer picks up the job:
queue.process('myQueue', function(job, done){
console.log('IN HERE', job.state) // returns function
});
This is the function that is returned from the above:
function ( state, fn ) {
if( 0 == arguments.length ) return this._state;
var client = this.client
, fn = fn || noop;
var oldState = this._state;
var multi = client.multi();
And I want to hardcode a job state e.g. job.state = 'failed' and allow myself to update the job status when I want to?
Is this possible in Kue?
Quick answer, yes, you can use job.failed() or send an error back to done.
queue.process('myQueue', function(job, done){
console.log('IN HERE', job.state) // returns function
job.failed();
done(new Error('bad'));
});
However, it sounds like you want to handle the processing yourself. You can setup your own function like this.
queue.on('job enqueue', function(id, type){
console.log( 'Job %s got queued of type %s', id, type );
kue.Job.get(id, function(err, job){
if (err) return;
// do your custom processing here
if( something was processed ){
job.complete();
}else{
job.failed();
}
});
});
Here's a few more options you can also use.
job.inactive();
job.active();
job.complete();
job.delayed();
There's some examples on this page.
https://github.com/Automattic/kue

Callback until for loop with query is done

I posted a question before and realized my problem actually was async functions. I managed to work out most of it, but I got one little problem left. Using async I used waterfall to create an order for the some queries...
exports.getMenu = function(id_restaurant, callback){
async.waterfall([
async.apply(firstQuery, id_restaurant),
secondQuery,
thirdQuery,
fourthQuery,
formMenu
], function(err, result){
if(err){
console.log(err);
}
callback(result);
});
};
Everything works until fourthQuery, where I have to loop to get all dishes of a menu.
function fourthQuery(array_totalP, array_nombresSecc, array_secciones, callback){
var size = array_nombresSecc.length;
var array_secciones = array_secciones;
var array_nombresSecc = array_nombresSecc;
var dishes = [];
pool.getConnection(function(err, connection) {
if(err) {
console.log(err);
callback(true);
return;
}
for (var i = 0; i < size; i++) {
connection.query("SELECT name, price FROM menu_product WHERE id_seccion = ? AND active = 1", [array_secciones[i]],
function(err, results2) {
if(err) {
console.log(err);
callback(true);
return;
}
console.log("Result query 4 " + JSON.stringify(results2));
dishes[i] = results2;
console.log("VALOR PLATILLOS EN i : " + JSON.stringify(dishes[i]));
// this prints the result but only if it has a value over 2
});
};
}); // pool
console.log("I'm sending " + dishes); // this logs an empty array
callback(null, dishes, array_nombresSecc);
};
So what i can see that happens from printing the value of 'i' each loop is that it always has the value of 2. Because that's 'size' value. Also, even though it's saving results of index '2' I believe the callback is being done even before the for loop is done, because my fifth function is recieving an empty array.
How can i make my code wait to callback until my for loop is done?
NOTE: Sorry, part of my code is in spanish, tried to translate the important parts of it.
There are a few ways to handle this, one is to look into promise architecture. Promise.all will let you supply one callback to handle the values from each child promise.
To use what you've already got, however, I'd push the values into your dishes array, rather than assigning them specifically to i indexes, then check the size of that array at the end of each connection. When the array length matches the size, fire the callback. (as seen below)
If you need a way to tie each result to that specific i value, I'd recommend pushing them as an object
dishes.push({'index': i, 'dish': results2})
Afterward, if you need the array of just dishes, you can sort the array by that index value and run a map function.
dishes.sort(function(a,b){ return a.index - b.index; })
dishes = dishes.map(function(a){ return a.dish })
Here's the code adjusted:
function fourthQuery(array_totalP, array_nombresSecc, array_secciones, callback) {
var size = array_nombresSecc.length;
var array_secciones = array_secciones;
var array_nombresSecc = array_nombresSecc;
var dishes = [];
pool.getConnection(function(err, connection) {
if (err) {
console.log(err);
callback(true);
return;
}
for (var i = 0; i < size; i++) {
connection.query("SELECT name, price FROM menu_product WHERE id_seccion = ? AND active = 1", [array_secciones[i]],
function(err, results2) {
if (err) {
console.log(err);
callback(true);
return;
}
console.log("Result query 4 " + JSON.stringify(results2));
dishes.push(results2)
if(dishes.length == size){
console.log("I'm sending " + dishes);
callback(null, dishes, array_nombresSecc)
}
console.log("VALOR PLATILLOS EN i : " + JSON.stringify(dishes[i]));
// this prints the result but only if it has a value over 2
});
};
}); // pool
;
};
Since you're already using the async, I would suggest replacing the for() loop in fourthQuery with async.each().
The updated fourthQuery would look like this:
function fourthQuery(array_totalP, array_nombresSecc, array_secciones, callback){
var size = array_nombresSecc.length;
var array_secciones = array_secciones;
var array_nombresSecc = array_nombresSecc;
var dishes = [];
pool.getConnection(function(err, connection) {
if(err) {
console.log(err);
callback(true);
return;
}
async.each(array_secciones,
function(item, itemCallback) {
// Function fun for each item in array_secciones
connection.query("SELECT name, price FROM menu_product WHERE id_seccion = ? AND active = 1", [item],
function(err, results2) {
if(err) {
console.log(err);
return itemCallback(true);
}
console.log("Result query 4 " + JSON.stringify(results2));
dishes.push(results2);
console.log("VALOR PLATILLOS EN i : " + JSON.stringify(dishes[dishes.length-1]));
// this prints the result but only if it has a value over 2
return itemCallback();
});
},
function(err) {
// Function run after all items in array are processed or an error occurs
console.log("I'm sending " + dishes); // this logs an empty array
callback(null, dishes, array_nombresSecc);
});
}); // pool
};
Alternatively, you can use async.map(), which handles gathering the results in the final callback so doesn't rely on the dishes variable.

Getting Undefined Variable in Javascript

UPDATED CODE: i, I'm new to Javascript programming and getting an undefined variable when trying to assign a new variable from a method.
I'm using node.js and creating a redis server using the redis-client in the "client variable".
var redis = require("redis");
var client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err); });
var numberPosts;
client.get("global:nextPostId", function(err, replies) {
numberPosts = replies;
console.log(numberPosts);
});
console.log(numberPosts);
When I call console.log inside the call back function it returns the proper value, however when I call the console.log outside of the callback function it returns "undefined". I'm trying to assign the value that is inside the callback function to the global variable numberPosts.
Any help is much appreciated, thanks.
Matt
I believe this will work:
client.get("global:nextPostId", function (err, reply) {
console.log("Number of posts: " + reply.toString());
})
The AJAX call is asynchronous so it doesn't have return value.. instead you have to use callback function and only there you have the value returned by the server method.
Edit: to assign the return value to global variable, first declare global variable:
var _numOfPosts = "";
Then:
client.get("global:nextPostId", function (err, reply) {
_numOfPosts = reply.toString());
})
However, the value won't be available until the AJAX call is finished so your original code can't work. There is not direct return value to store.
You can set timer to some reasonable response time, then have the code using the global variable in there.
Edit II: in order to call the method again once it's finished, have such code:
var _nextPostCallCount = 0;
function GetNextPost() {
//debug
console.log("GetNextPost called already " + _nextPostCallCount + " times");
//sanity check:
if (_nextPostCallCount > 1000) {
console.log("too many times, aborting");
return;
}
//invoke method:
client.get("global:nextPostId", function(err, replies) {
numberPosts = parseInt(replies.toString(), 10);
console.log("num of replies #" + (_nextPostCallCount + 1) + ": " + numberPosts);
//stop condition here.... for example if replies are 0
if (!isNaN(numberPosts) && numberPosts > 0)
GetNextPost();
});
//add to counter:
_nextPostCallCount++;
}
GetNextPost();
This will call the method over and over until the result is 0 or you pass some hard coded limit to prevent endless loop.
Try this instead to see errors:
var redis = require("redis");
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err); });
//note the error logging
var numberPosts = client.get("global:nextPostId", function (error, response) {
if (error) {
console.log("async: " + error);
} else {
console.log("programming: " + response);
}
});
console.log("is lotsa fun: " + numberPosts);
As Shadow Wizard has pointed out you are trying to use numberPosts before there is something in it, as client.get() hasn't returned anything.
Read this to get a handle on node.js flow:
http://www.scribd.com/doc/40366684/Nodejs-Controlling-Flow
I was facing the the same issue when I applied the MVC framework.
To solve the problem, I employed the render function.
In the posts Model
exports.get = function(id,render) {
client.incr('post:id:'+id, function(err, reply) {
render(reply);
});
};
In the posts Controller
exports.get = function(req, res) {
posts.get('001', function (data){res.render('index',{post:data});});
};

Categories