MEAN Nodejs JSON.parse passing data from client to server - json

I am using MEAN stack and I am sending query parameters dynamically to my Nodejs server endpoints.
My client controller :
$http.get('/api/things',{params:{query:query}}).then(response => {
this.awesomeThings = response.data;
socket.syncUpdates('thing', this.awesomeThings);
});
where query is a value injected into the controller.
This is the server controller function (which works):
export function index(req, res) {
var query = req.query.query && JSON.parse(req.query.query)
Thing.find(query).sort({_id:-1}).limit(20).execAsync()
.then(respondWithResult(res))
.catch(handleError(res));
}
The above works but I am trying to understand the line
var query = req.query.query && JSON.parse(req.query.query)
as I have never seen this before( and I don't come from a programming background). I console.logged query and understand it's an object (which is required by Mongodb) but when I console.logged (JSON.parse(req.query.query)) or JSON.parse(query) to find out the final output, the program stops working with no error messages, very strange..
If someone can explain the above syntax and why it has to be done this way for it work, that would be much appreciated..
PS when I try to console log the JSON.parse like so, it fails to load even though it should have no effect whatsoever:
export function index(req, res) {
var query = req.query.query && JSON.parse(req.query.query)
var que = JSON.parse(req.query.query)
Thing.find(query).sort({_id:-1}).limit(20).execAsync()
.then(respondWithResult(res))
.catch(handleError(res));
console.log("que"+que)
}

function one() {
var x = {};
var res = JSON.parse(x.y);
console.log(res);
}
function two() {
var x = {};
var res = x.y && JSON.parse(x.y);
console.log(res);
}
<button onclick="one()">ERROR</button>
<button onclick="two()">NO ERROR</button>
var x = data && JSON.parse(data);
Since expression is evaluated from left, first data is evaulated.
If it is undefined then, the next part -> JSON.parse() is not performed.
On the other hand, if data is defined parse is tried and the result is returned and stored in x.
Main advantage here is the parse doesn't run if the variable wasn't defined.
it could be equivalent to saying:
if(data) {x = JSON.parse(x);}

Related

Node.js trying to use async/await to get data from a mysql select before using the variable

I need to catch some data by a mysql query, and use the result to build up and email message with its results with node.
I put the code inside a function, but the call to the query appear to still be async, as the result is never given back before the end of the function, and the returning variable is alwasy empty.
Tried different approach with async/await but still the execution seems async
In my following code is just get in the console log up to the step 3, the step 4 is mde no matter what I try to do at the end of the function call
async function querydb (utente){
console.log("sono in querydb");
var messageHTMLAllegati="";
var risultatoquery;
console.log("step 1");
var connection = mysql.createConnection({
host : process.env.IP_address,
user : process.env.nome_utente,
password : process.env.password,
port : process.env.port,
database : process.env.DB,
});
console.log("step 2");
const query = util.promisify(connection.query).bind(connection);
(async () => {
try {
console.log("step 3");
var result = await query('SELECT Link FROM Link_Foto where ID_Utente="' + utente + '"');
var i = result.length;
console.log("step 4");
var j ;
for (j=0; j < i; j++) {
messageHTMLAllegati +='Immagine ' + (j+1)+ '<BR>';
console.log("print the link found in the DB and added to the text to be printed"+result[j].Link);
}
} finally {
connection.end();
}
})()
return messageHTMLAllegati;
}
I do expect the final variable "messageHTMLAllegati" to contain some text plus the query fields needed, but it get always empty. In the log I see though that the variable is filled up, but only after that the function is returned, therefore the text used to put the email together is empty from the DB section
async/await method only works when await functions is a promise. functions like 'query' in mysql are using a callback function to get the result. So if you want to use it with async/await method you should use it in another function and get the result in its callback function as a promise like this:
function query_promise(q_string){
return new Promise((resolve, reject)=>{
query(q_string,(err, result)=>{
if(err) return reject(err);
resolve(result);
});
});
}
then in your code:
var result = await query_promise('SELECT Link FROM Link_Foto where ID_Utente="' + utente + '"');

Confused on how notes = JSON.parse(noteString);

var addnote = function (title, body) {
var notes = [];
var note = {
title: title,
body: body
}
need explanation on the two lines under try
try {
var noteString = fs.readFileSync("data.json");
notes = JSON.parse(noteString);
} catch (e) {
}
And explanation on how duplicateNotes works ..
var duplicateNotes = notes.filter(function(note){
return note.title === title
})
if (duplicateNotes.length === 0) {
notes.push(note);
fs.writeFileSync("data.json", JSON.stringify(notes));
}
}
JSON.parse converts a JSON object to String.
{
field1:field1Value,
field2:fieldValue
}
If this is in Json format you can access it's elements using JSONObjectName.fieldName
But,if it's converted to String it looses it's JSON properties. You can't access fields in same way. Output will act like String.
need explanation on the two lines under try
var noteString = fs.readFileSync("data.json");
There are two kinds of response back asynchronous and synchronous. Synchronous call is like you will not start playing until you get a pass and score a goal. But, Asynchronous call is like you start playing with your friend but, you run near him and, there is a promise you won't shoot until you get the ball.
readFileSync will read the file and the next line will wait until it gets the pass.JSON.parse() will convert file content to JSON object.
And explanation on how duplicateNotes works ..
var duplicateNotes = notes.filter(function(note){
return note.title === title
})
Whenever a match is found , that element in notes will be pushed to duplicate note. That's all.

node.js: put asynchronous returns in one object or array

I am missing something fundamental in terms of callbacks/async in the code below: why do I get:
[,,'[ {JSON1} ]']
[,,'[ {JSON2} ]']
(=2 console returns) instead of only one console return with one proper table, which is want I want and would look like:
[,'[ {JSON1} ]','[ {JSON2} ]']
or ideally:
[{JSON1},{JSON2}]
See my code below, getPTdata is a function I created to retrieve some JSON via a REST API (https request). I cannot get everything at once since the API I'm talking to has a limit, hence the limit and offset parameters of my calls.
offsets = [0,1]
res = []
function goGetData(callback) {
for(var a = 0; a < offsets.length; a++){
getPTdata('stories',
'?limit=1&offset='+offsets[a]+'&date_format=millis',
function(result){
//called once getPTdata is done
res[a] = result
callback(res)
});
}
}
goGetData(function(notgoingtowork){
//called once goGetData is done
console.log(res)
})
Solved like this:
offsets = [0,1]
res = []
function goGetData(callback) {
var nb_returns = 0
for(var a = 0; a < offsets.length; a++){
getPTdata('stories','?limit=1&offset='+offsets[a]+'&date_format=millis', function(result){
//note because of "loop closure" I cannot use a here anymore
//called once getPTdata is done, therefore we know result and can store it
nb_returns++
res.push(JSON.parse(result))
if (nb_returns == offsets.length) {
callback(res)
}
});
}
}
goGetData(function(consolidated){
//called once goGetData is done
console.log(consolidated)
})

Trying to interpret the Node-Neo4j API

I'm pretty new to coding so forgive me if my code is unreadable or my question simplistic.
I am trying to create a little server application that (amongst other things) displays the properties of a neo4j node. I am using node.js, Express and Aseem Kishore's Node-Neo4j REST API client, the documentation for which can be found here.
My question stems from my inability to fetch the properties of nodes and paths. I can return a node or path, but they seem to be full of objects with which I cannot interact. I poured through the API documents looking for some examples of how particular methods are called but I found nothing.
Ive been trying to call the #toJSON method like, "db.toJSON(neoNode);" but it tells me that db does not contain that method. I've also tried, "var x = neoNode.data" but it returns undefined.
Could someone please help me figure this out?
//This file accepts POST data to the "queryanode" module
//and sends it to "talkToNeo" which queries the neo4j database.
//The results are sent to "resultants" where they are posted to
//a Jade view. Unfortuantly, the data comes out looking like
// [object Object] or a huge long string, or simply undefined.
var neo4j = require('neo4j');
var db = new neo4j.GraphDatabase('http://localhost:7474');
function resultants(neoNode, res){
// if I console.log(neoNode) here, I now get the 4 digit integer
// that Neo4j uses as handles for nodes.
console.log("second call of neoNode" + neoNode);
var alpha = neoNode.data; //this just doesn't work
console.log("alpha is: " +alpha); //returns undefined
var beta = JSON.stringify(alpha);
console.log("logging the node: ");
console.log(beta);// still undefined
res.render("results",{path: beta});
res.end('end');
}
function talkToNeo (reqnode, res) {
var params = {
};
var query = [
'MATCH (a {xml_id:"'+ reqnode +'"})',
'RETURN (a)'
].join('\n');
console.log(query);
db.query(query, params, function (err, results) {
if (err) throw err;
var neoNode = results.map(function (result){
return result['a']; //this returns a long string, looks like an array,
//but the values cannot be fetched out
});
console.log("this is the value of neoNode");
console.log(neoNode);
resultants(neoNode, res);
});
};
exports.queryanode = function (req, res) {
console.log('queryanode called');
if (req.method =='POST'){
var reqnode = req.body.node; //this works as it should, the neo4j query passes in
talkToNeo(reqnode, res) //the right value.
}
}
EDIT
Hey, I just wanted to answer my own question for anybody googling node, neo4j, data, or "How do I get neo4j properties?"
The gigantic object from neo4j, that when you stringified it you got all the "http://localhost:7474/db/data/node/7056/whatever" urls everywhere, that's JSON. You can query it with its own notation. You can set a variable to the value of a property like this:
var alpha = unfilteredResult[0]["nodes(p)"][i]._data.data;
Dealing with this JSON can be difficult. If you're anything like me, the object is way more complex than any internet example can prepare you for. You can see the structure by putting it through a JSON Viewer, but the important thing is that sometimes there's an extra, unnamed top layer to the object. That's why we call the zeroth layer with square bracket notation as such: unfilteredResult[0] The rest of the line mixes square and dot notation but it works. This is the final code for a function that calculates the shortest path between two nodes and loops through it. The final variables are passed into a Jade view.
function talkToNeo (nodeone, nodetwo, res) {
var params = {
};
var query = [
'MATCH (a {xml_id:"'+ nodeone +'"}),(b {xml_id:"' + nodetwo + '"}),',
'p = shortestPath((a)-[*..15]-(b))',
'RETURN nodes(p), p'
].join('\n');
console.log("logging the query" +query);
db.query(query, params, function (err, results) {
if (err) throw err;
var unfilteredResult = results;
var neoPath = "Here are all the nodes that make up this path: ";
for( i=0; i<unfilteredResult[0]["nodes(p)"].length; i++) {
neoPath += JSON.stringify(unfilteredResult[0]['nodes(p)'][i]._data.data);
}
var pathLength = unfilteredResult[0].p._length;
console.log("final result" + (neoPath));
res.render("results",{path: neoPath, pathLength: pathLength});
res.end('end');
});
};
I would recommend that you look at the sample application, which we updated for Neo4j 2.0
Which uses Cypher to load the data and Node-labels to model the Javascript types.
You can find it here: https://github.com/neo4j-contrib/node-neo4j-template
Please ask more questions after looking at this.

Promisify a recursive function in node.js

I'm using bluebird for the control flow in my application, I'm trying to implement promisify to extend my recursive function into a promise, but it seems like the "then" method never got executed
I'm doing a mapping from one JSON object to another, the find function looks recursively into the JSON properties and returns the property based on an specific condition.
var promise = require("bluebird");
var mapToModel = function(res){
// res is a json structure
var processes = res.definitions.process;
var diagrams = res.definitions.BPMNDiagram;
var documents = [];
for(var prop in processes) {
if(processes.hasOwnProperty(prop)){
var propertyNames = Object.getOwnPropertyNames(processes[prop]);
for(var property in processes[prop]){
var mapping ={};
if(property==="$"){
//do something with the process
}else{
//shapes
mapping.hash = hash.hashCode(new Date().toString());
mapping.type = property;
mapping.value = processes[prop][property];
var bpmnItem = findPromise(processes[prop][property], function(x) {return x.$.id;}).then(function(value){
//I'm not reaching this point
var bpmnId = value.$.id;
console.log(value);
if(bpmnId!=undefined){
console.log("return:"+ bpmnId);
}
});
documents.push(mapping);
}
}
}
return documents;
}
}
var findPromise = promise.promisify(find);
function find(items,f) {
for(var key in items) {
var elem = items[key];
if (f(elem)) { return elem;}
if(typeof elem === "object") {
find(elem,f); // call recursively
}
}
}
The Bluebird promisify method works on the accepted callback convention for NodeJS - nodebacks.
Nodebacks are in the specific format of someOp(function(err,result){ that is - the first argument is always an error.
In fact, your find method is not even asynchronous, so there is no reason to promisify it to begin with. You can simply call it as it is.
Generally, you should not promisify synchronous functions, you just call them normally. In fact, you don't seem to have any asynchronous operation in your code - so you should not be using promises at all in it.
You can simply do:
mapping.value = processes[prop][property];
var value = find(processes[prop][property], function(x) {return x.$.id;});
var bpmnId = value.$.id;
console.log(value);
if(bpmnId!=undefined){
console.log("return:"+ bpmnId);
}
Remember, Promises are an abstraction over an eventual result. You keep doing everything synchronous just like you did before.