Trying to interpret the Node-Neo4j API - json

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.

Related

Save result to variable?

So I have been developing a note taking app, and I am having some trouble with displaying the username! Normally you would get a result like this:
con.query('SELECT someVariable FROM someColumn', function (result) {
console.log(result)
})
But I would like to save the result to a variable like this:
var variable = '';
con.query('SELECT someVariable FROM someColumn', function (result) {
variable = result
})
console.log("Here is some data: " + variable)
But that obviously wouldn't work. So how can I do this???
The point
How would I save a mySQL result to a variable, so it can be used later in my code? Also Im not an experienced developer so you might have to do a bit more explaining that usual, thanks.
If you're new to Node and/or JavaScript then you've just stumbled on one of the major problems of asynchronous programming. Here's your code as the JavaScript runtime sees it:
// Declare variable
var variable = '';
var callback = function(result) {
variable = result;
};
// This code runs right away
con.query('SELECT someVariable FROM someColumn', callback);
// Then this code runs
console.log("Here is some data: " + variable);
// Then, a thousand years later (from a CPU's perspective) this callback executes
callback(result);
You can see you're jumping the gun here. You can't depend on any behaviour until the callback has run, or in other words, you need to put any dependent behaviour inside the callback.
Since it's 2020 you can also do this with async and await if you're using a Promise-capable library. Your code could look like:
// Assign variable to the result of the query call, waiting as long as necessary
let variable = await con.query('SELECT someVariable FROM someColumn');
console.log("Here is some data: " + variable);
This will be properly sequenced.

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.

Write specific API data to JSON file

I want to be able to only save specific data from the output of the API...
function getGiph() {
giphy.search({
q: 'pratt',
}, function (err, res) {
var gif = res.data;
for (var i = 0; i < gif.length; i++) {
var embed = gif[i].embed_url;
fs.writeFile('./apidata.json', JSON.stringify(embed, undefined, 1), function (err) {
if (err) throw err;
console.log('saved');
});
}
});
}
This is my code, when I console.log(embed); it outputs only the embed_urls of the API in the terminal just like I want, but when I write to the JSON it outputs "https://giphy.com/embed/XqOCxN1WpEzja"MsM0"" and that is all...
If I replace 'embed' with 'gif' in the fs.writeFile(), then of course it writes the entire API data to the JSON.
I have tried JSON.stringify(gif, undefined, 1),
JSON.stringify(embed, undefined, 1).
I honestly searched and searched I hardly ever ask questions because I almost always find a solution but this one has me, I am pretty new to all this as well.

MEAN Nodejs JSON.parse passing data from client to server

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);}

nightwatch.js return value from function outside a test

I have trouble moving certain code outside a test into a function that needs to return a value.
Here is part of my code for the test file
function getCountOfTopics(browser){
var count;
browser.getText('#sumTopics',
function(result){
count = result.value;
console.log(result.value);
}
);
return count;
};
module.exports = {
'Create article' : function(browser){
var noOfThreadsByInlineCode, noOfThreadsByFunction;
browser.getText('#sumTopics',
function(result){
noOfThreadsByInlineCode = result.value;
}
);
noOfThreadsByFunction = getCountOfTopics(browser);
browser.end();
}
}
Now, the variable noOfThreadsByInlineCode indeed gets the value in the DOM, but the variable noOfThreadsByFunction is undefined. The console does indeed print the correct value, so the function does get the correct value out of the DOM.
I would appreciate help in updating the function so that I do get the value returned.
One word answer is Asynchronisity. The code doesn't wait for your callback to get complete, thats what the feature of Node JS is.
If you are in desperately in need for the content inside of the callback you can write this variable into a file and then access it anywhere you want inside your code. Here's a bit of a workaround:
Save something in a file:
var fs = require('fs');
iThrowACallBack(function(response){
fs.writeFile('youCanSaveData.txt', this.response, function(err) {
if (err) throw err;
console.log('Saved!');
browser.pause(5000);
});
});
Access it somewhere else:
iAccessThefile(){
response = fs.readFileSync('youCanSaveData.txt').toString('utf-8');
}
Hope it helps.
You return variable 'count' outside the callback,that is why.You can take a look this topic How to return value from an asynchronous callback function?
function getCountOfTopics(browser){
var count;
browser.getText('#sumTopics',
function(result){
count = result.value;
console.log(result.value);
/// result.value is available in this callback.
}
);
What do you want to do with the 'value'?
ps:do not remember custom_command.I think it is very helpful for this issue.