Neo4j/cypher: Return id as property - neo4j

I've got this super simple cypher query for my juicy graph database of two nodes:
MATCH (n) RETURN n
And it's returning the two nodes as such:
{
"results": [
{
"columns": [
"n"
],
"data": [
{
"row": [
{
"name": "node 1",
"description": "This is my first node."
}
]
},
{
"row": [
{
"name": "node 2",
"description": "This is my second node."
}
]
}
]
}
],
"errors": []
}
I was kind of expecting to get the id out as a property with "name" and "description". How can i get it in there? I know I can go something like:
MATCH (n) RETURN n, id(n)
But that would put the id outside the object and I don't want that.

You can use map {foobar:42}and collection structures in Cypher [1,2,3]
so you can return:
RETURN {id:id(n), labels: labels(n), data: n}
or you can use
{"statement":"match (n) return n","resultDataContents":["graph"]}
as additional parameter to your POST request.

Related

Issue in Cypher Query - org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException

I am performing below steps using cypher query. I am getting error in step 3. I have listed all steps below. Please help me to achieve expected output.
Step 1- Load data and define properties of nodes relationship
LOAD CSV WITH HEADERS FROM 'file://nodes_1Jan22_full_v2.csv' AS row
CREATE (n: Organisation {id: row.organisation, esg_index: toFloat(row.tone)});
LOAD CSV WITH HEADERS FROM 'file://edges_1Jan22_full_v2.csv' AS row
MERGE (src: Organisation {id: row.src})
MERGE (dst: Organisation {id: row.dst})
MERGE (src)-[:RELATE {freq: toInteger(row.relationship), sentiment: toFloat(row.avg_tone)}]->(dst);
Sample query and table structure
MATCH p=()-[r:RELATE]->() RETURN p LIMIT 1
{
"start": {
"identity": 18862,
"labels": [
"Organisation"
],
"properties": {
"id": "american university",
"esg_index": -3.005288932058546
}
},
"end": {
"identity": 20048,
"labels": [
"Organisation"
],
"properties": {
"id": "duke university",
"esg_index": -1.6810932825414502
}
},
"segments": [
{
"start": {
"identity": 18862,
"labels": [
"Organisation"
],
"properties": {
"id": "american university",
"esg_index": -3.005288932058546
}
},
"relationship": {
"identity": 0,
"start": 18862,
"end": 20048,
"type": "RELATE",
"properties": {
"sentiment": -4.367701625823974,
"freq": 250
}
},
"end": {
"identity": 20048,
"labels": [
"Organisation"
],
"properties": {
"id": "duke university",
"esg_index": -1.6810932825414502
}
}
}
],
"length": 1.0
}
Step 2- Create graph projection
CALL gds.graph.project(
'gdelt-analytics',
'Organisation',
'RELATE',
{
relationshipProperties: 'freq'
}
)
MATCH (org:Organisation {id: 'public health'})
CALL gds.pageRank.stream('gdelt-analytics', {
maxIterations: 100,
dampingFactor: 0.85,
sourceNodes: [org],
relationshipWeightProperty: 'freq'
})
YIELD nodeId, score
RETURN *
Current Output
Step 3- Attempt to color node based on property "esg_index" and edges based on property "sentiment" (Query that is throwing error)
CALL apoc.create.addLabels(n.esg_index, [apoc.text.upperCamelCase(n.id)]) YIELD node
RETURN *
Neo.ClientError.Procedure.ProcedureCallFailed
Failed to invoke procedure apoc.create.addLabels: Caused by: org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException: Unable to load NODE with id -2.
Expected Output
Graph with nodes and edges colored. Nodes colored based on esg_index and edges colored based on sentiment
The APOC addLabels function takes either a list of nodes or their id, which can be found using ID(n), as its input. You are passing esg_index, that's why you might be getting this error:
Try this:
CALL apoc.create.addLabels(n, [apoc.text.upperCamelCase(n.id)]) YIELD node
RETURN *
It should work. Documentation link.
Update:
To add the label using esg_index, I think apoc.do.case function should do the trick for you. You can try something like this:
CALL apoc.do.case([
n IS NOT NULL AND n.esg_index = -5,
'SET n:DARK_RED RETURN n AS node',
n IS NOT NULL AND n.esg_index = 1,
'SET n:GREEN RETURN n AS node'
],
'RETURN n AS node',{n: n})
YIELD value
RETURN value.node AS node;

Return nodes together with relations

I'm playing with Cypher and Neo4j a bit and I created a simple graph:
CREATE (j: person { name: "james" })
CREATE (m: person { name: "mary" })
CREATE (j)<-[:friends_with]-(m)
If I return all the nodes:
MATCH (m) RETURN m
in the graph view I get:
but the response JSON is:
[
{
"keys": [
"m"
],
"length": 1,
"_fields": [
{
"identity": {
"low": 3,
"high": 0
},
"labels": [
"person"
],
"properties": {
"name": "james"
}
}
],
"_fieldLookup": {
"m": 0
}
},
{
"keys": [
"m"
],
"length": 1,
"_fields": [
{
"identity": {
"low": 4,
"high": 0
},
"labels": [
"person"
],
"properties": {
"name": "mary"
}
}
],
"_fieldLookup": {
"m": 0
}
}
]
which contains the list of nodes, but no information about the relationship between nodes.
Is it possible to also get the full graph/the relationship between nodes if certain returned nodes have relationships defined between one another?
If you want to retrieve relationship information, you must request it in your Cypher request.
For example, if you want to retrieve all the nodes with a friends_with relationship
MATCH (a:person)-[r:friends_with]-(b:person) RETURN a,r,b
Thus you will recover the nodes and the relationships of the people concerned.
Of course, you can adapt this query, depending on whether you want to know only the original node, only have the relation, etc ...
If you want to get ALL the nodes with an is_friends relation:
MATCH (a)-[r:friends_with]-() RETURN a,r
So you will turn all the node and the relationship too

Cypher Query: Return type of relationship of paths with variable length

users,
I am trying to receive all paths (e.g., length < 3) , print the node titles, but also the relationship type.
Using:
MATCH (p0:Page {title:'New Zealand'}), (p1:Page {title:'Kiwi'}), p = (p0)-[r*..2]-(p1)
RETURN p AS path
Prints the paths, but the relationship is represented as {}
As I am using *..2,
`RETURN p,type(r)'
is not working(Type mismatch: expected Relationship but was Collection)
I can use a workaround like:
MATCH
(p0:Page {title:'New Zealand'}),
(p1:Page {title:'Kiwi'}),
p = (p0)-[r]-(p3)-[r1]-(p1)
RETURN p0,type(r),p3,type(r1)
but with increasing pathlength, I would have executed a query for each pathlength.
I tried:
MATCH
(p0:Page {title:'New Zealand'}),
(p1:Page {title:'Kiwi'}),
p = (p0)-[r*..2]-(p1) FOREACH(r in p | RETURN p,p0,type(r),p1)
-> expected Collection but was Path
Does anyone have hint?
Additional information JSON output(snippet) from Neo4j interface:
{
"results": [
{
"columns": [
"p",
"rels(p)",
"nodes(p)"
],
"data": [
{
"row": [
[
{
"title": "New Zealand"
},
{},
{
"title": "Category:Birds of New Zealand"
},
{},
{
"title": "Kiwi"
}
],
[
{},
{}
],
[
{
"title": "New Zealand"
},
{
"title": "Category:Birds of New Zealand"
},
{
"title": "Kiwi"
}
]
],
"graph": {
"nodes": [
{
"id": "11120",
"labels": [
"Page"
],
"properties": {
"title": "Kiwi"
}
},
{
"id": "1942858",
"labels": [
"Page"
],
"properties": {
"title": "New Zealand"
}
},
{
"id": "11994493",
"labels": [
"Category"
],
"properties": {
"title": "Category:Birds of New Zealand"
}
}
],
"relationships": [
{
"id": "1070940",
"type": "To_Category",
"startNode": "11120",
"endNode": "11994493",
"properties": {}
},
You can simply use extract for extracting the type of relationships inside the path.
Based on the simple movie graph on http://console.neo4j.org :
MATCH p=(:Crew { name:"Neo" })-[r*3]-()
RETURN p, extract(x IN rels(p)| type(x)) AS types
Your query would then be :
MATCH (p0:Page {title:'New Zealand'}), (p1:Page {title:'Kiwi'}),
p=(p0)-[r*..2]-(p1)
RETURN p, extract (rel in rels(p) | type(rel) ) as types
This will return you a collection of types :
[LOVE, KNOWS, KNOWS]
So you can have duplicates. If you need to de-duplicate them, use UNWIND and distinct :
MATCH (p0:Page {title:'New Zealand'}), (p1:Page {title:'Kiwi'}),
p=(p0)-[r*..2]-(p1)
WITH p, extract (rel in rels(p) | type(rel) ) as types
UNWIND types as t
RETURN p, collect(distinct t) as types
UPDATE
I wasn't so happy with the last one, so here an easier way :
MATCH (p0:Page {title:'New Zealand'}), (p1:Page {title:'Kiwi'}),
p=(p0)-[r*..2]-(p1)
UNWIND rels(p) as rel
RETURN p, collect(distinct type(rel)) as types
Does using the rels function help you?
MATCH (p0:Page {title:'New Zealand'}), (p1:Page {title:'Kiwi'}), p = (p0)-[r*..2]-(p1)
RETURN p, rels(p), nodes(p)

How to return relationship type with Neo4J's Cypher queries?

I am trying to get the relationship type of a very simple Cypher query, like the following
MATCH (n)-[r]-(m) RETURN n, r, m;
Unfortunately this return an empty object for r. This is troublesome since I can't distinguish between the different types of relationships. I can monkey patch this by adding a property like [r:KNOWS {type:'KNOWS'}] but I am wondering if there isn't a direct way to get the relationship type.
I even followed the official Neo4J tutorial (as described below), demonstrating the problem.
Graph Setup:
create (_0 {`age`:55, `happy`:"Yes!", `name`:"A"})
create (_1 {`name`:"B"})
create _0-[:`KNOWS`]->_1
create _0-[:`BLOCKS`]->_1
Query:
MATCH p=(a { name: "A" })-[r]->(b)
RETURN *
JSON RESPONSE BODY:
{
"results": [
{
"columns": [
"a",
"b",
"p",
"r"
],
"data": [
{
"row": [
{
"name": "A",
"age": 55,
"happy": "Yes!"
},
{
"name": "B"
},
[
{
"name": "A",
"age": 55,
"happy": "Yes!"
},
{},
{
"name": "B"
}
],
{}
]
},
{
"row": [
{
"name": "A",
"age": 55,
"happy": "Yes!"
},
{
"name": "B"
},
[
{
"name": "A",
"age": 55,
"happy": "Yes!"
},
{},
{
"name": "B"
}
],
{}
]
}
]
}
],
"errors": []
}
As you can see, I get an empty object for r, which makes it impossible to distinguish between the relationships.
NOTE: I am running Neo4J v.2.2.2
Use the type() function.
MATCH (n)-[r]-(m) RETURN type(r);
Added distinct.
MATCH (n)-[r]-(m) RETURN distinct type(r);

neo4j rest API resultDataContents:graph does not really returns one graph?

To make yet another d3 viewer, I'd like to get a graph out from a rest query.
In my understanding, stating 'resultDataContent':['graph'] would return a graph. Instead, it return a list of subgraphs and I need therefore to collect and distinct the nodes. Is there a way to get the full sub graph simply?
For example, I put these 4 nodes
CREATE (a:Person {name:'a'})
CREATE (b:Person {name:'b'})
CREATE (c:Person {name:'c'})
CREATE (d:Person {name:'d'})
CREATE (a)-[:KNOWS]->(b)
CREATE (a)-[:KNOWS]->(c)
CREATE (b)-[:KNOWS]->(c)
CREATE (c)-[:KNOWS]->(d)
But calling a POST query with the following query will return 2 results.data, each of them with a "graph", consisting of 2 nodes and a links?
{"statements":[
{
"statement":"MATCH (p:Person {name:{pName}})-[l:KNOWS]-(q:Person) RETURN p,l,q",
"parameters":{"pName":"a"},
"resultDataContents":["graph"]
}
]}
Is there a way to return the one subgraph, without the need to reassemble the results?
Thanks for the help,
Alex
I think the issue is that the same person will be returned twice by your query. Change the return statement to:
RETURN collect(distinct(p)),collect(l),collect(distinct(q))
That will give you the following response:
{
"results": [
{
"columns": [
"collect(distinct(p))",
"collect(l)",
"collect(distinct(q))"
],
"data": [
{
"graph": {
"nodes": [
{
"id": "1849644",
"labels": [
"Person"
],
"properties": {
"name": "b"
}
},
{
"id": "1849645",
"labels": [
"Person"
],
"properties": {
"name": "c"
}
},
{
"id": "1849643",
"labels": [
"Person"
],
"properties": {
"name": "a"
}
}
],
"relationships": [
{
"id": "4052753",
"type": "KNOWS",
"startNode": "1849643",
"endNode": "1849644",
"properties": {}
},
{
"id": "4052754",
"type": "KNOWS",
"startNode": "1849643",
"endNode": "1849645",
"properties": {}
}
]
}
}
]
}
],
"errors": []
}
Whilst working on something similar (https://stackoverflow.com/questions/26067792/neo4j-cypher-gui) I've run into the same problem. The documentation: http://docs.neo4j.org/chunked/stable/rest-api-transactional.html is very light on the subject

Resources