neo4jrestclient - query get id - neo4j

I am using the neo4jrestclient library.
from neo4jrestclient.client import GraphDatabase
from neo4jrestclient import client
from neo4jrestclient import query
gdb = GraphDatabase("http://localhost:7474/db/data/")
q = """MATCH n RETURN n;"""
result = gdb.query(q=q)
print(result[0])
When I am executing the query "MATCH n RETURN n, the output is:
[{
'all_relationships': 'http://localhost:7474/db/data/node/1131/relationships/all',
'all_typed_relationships': 'http://localhost:7474/db/data/node/1131/relationships/all/{-list|&|types}',
'self': 'http://localhost:7474/db/data/node/1131',
'labels': 'http://localhost:7474/db/data/node/1131/labels',
'properties': 'http://localhost:7474/db/data/node/1131/properties',
'create_relationship': 'http://localhost:7474/db/data/node/1131/relationships',
'outgoing_relationships': 'http://localhost:7474/db/data/node/1131/relationships/out',
'data': {
'title': 'title',
'name': 'Poludnie'
},
'incoming_typed_relationships': 'http://localhost:7474/db/data/node/1131/relationships/in/{-list|&|types}',
'property': 'http://localhost:7474/db/data/node/1131/properties/{key}',
'paged_traverse': 'http://localhost:7474/db/data/node/1131/paged/traverse/{returnType}{?pageSize,leaseTime}',
'incoming_relationships': 'http://localhost:7474/db/data/node/1131/relationships/in',
'outgoing_typed_relationships': 'http://localhost:7474/db/data/node/1131/relationships/out/{-list|&|types}',
'traverse': 'http://localhost:7474/db/data/node/1131/traverse/{returnType}'}]
I see that the node’s id = 1131. The question is: can I obtain this id in raw forms without those links? I would like to have only the id together with the value of the ‘data’ field.

In Cypher, that could be expressed like this:
MATCH (n) RETURN {id: ID(n), name: n.name, title: n.title} as city
In the response, the data hash will contain an array and each element's row key will contain this data accessible using their given keys.

To get "just the id and data, change your query to:
MATCH (n) RETURN id(n), n.data
See if that is satisfactory.

Related

Return relations as child nodes in tree (Neo4j Cypher)

Is there a way to retrieve relations as child elements of a tree?
This is the basic data i have:
CREATE (:Customer {id:1, name:'Customer 1'})<-[:CREATED_BY]-(c:Category {id:1, name:'Category 1'})
WITH c as category, range(2, 7) as subCatIds
FOREACH (s IN subCatIds | CREATE (category)<-[:SUBCATEGORY_OF]-(:Category {id:s, name:'SubCategory '+s}))
WITH category, range(1, 5) as attTypeIds
FOREACH (a IN attTypeIds | CREATE (category)-[:HAS_ATTRIBUTE {name:'Attribute '+a, required: (a%2=0)}]->(:AttributeType {id:a, name:'AttributeType '+a}))
WITH category
MATCH p = (:AttributeType)<-[:HAS_ATTRIBUTE]-(category)<-[:SUBCATEGORY_OF]-(:Category)
RETURN p
So this query returns correctly the tree structure:
MATCH (:Customer {id:1})<-[:CREATED_BY]-(c:Category {id:1}),
p = (c)<-[:SUBCATEGORY_OF*0..1]-(:Category)
WITH COLLECT(p) as category
CALL apoc.convert.toTree(category) yield value
RETURN value
How do i add the relationships [:HAS_ATTRIBUTE] as child nodes to this query?
I've tried already:
MATCH (:Customer {id:1})<-[:CREATED_BY]-(c:Category {id:1}),
SubCatsP = (c)<-[:SUBCATEGORY_OF*0..1]-(:Category),
AttP = (c)-[:HAS_ATTRIBUTE]->(att:AttributeType)
WITH COLLECT(SubCatsP) as category, RELATIONSHIPS(AttP) as attributes
CALL apoc.convert.toTree(category) yield value
RETURN value, attributes
But this returns 5 records (1 for each relationship [:HAS_ATTRIBUTE]) with the Category-Subcategories tree repeated.
I expect the result to be:
{
id: 1,
name: 'Category 1',
SUBCATEGORY_OF:[
{id:2, name: 'Subcategory 2'}, ...
]
HAS_ATTRIBUTE:[
{name: 'Attribute 1', required: false, att: {name:'AttributeType 5',id:5}}, ...
<OR>
{name: 'Attribute 1', required: false, att.name:'AttributeType 5',att.id:5}, ...
]
}
Is this even possible or do you consider a better approach to perform 2 separate queries?
You can try combining the paths into a single list:
MATCH (:Customer {id:1})<-[:CREATED_BY]-(c:Category {id:1}),
SubCatsP = (c)<-[:SUBCATEGORY_OF*0..1]-(:Category),
AttP = (c)-[:HAS_ATTRIBUTE]->(att:AttributeType)
WITH COLLECT(SubCatsP) + COLLECT(AttP) as category
CALL apoc.convert.toTree(category) yield value
RETURN value

Returning a new graph with Cypher or OpenCypher

This question comes from experience with the CONSTRUCT operator in SPARQL, which allows to take variable bindings in a graph query and return a new graph as result.
Is there anything like that in Cypher/OpenCypher?
I mean, suppose you have:
react1 - [part-of] -> pathway1
mol1 - [consumed-by] -> react1
mol2 - [consumed-by] -> react1
mol3 - [produced-by] -> react1
I'd like to return a simplified graph like:
pathway1 - [input] - mol1
pathway1 - [input] - mol2
pathway1 - [output] - mol3
Note that I've already played with WITH/COLLECT/UNWIND to return JSON structures very similar to the graph above, but this approach is much more difficult to write.
You can experiment with virtual relationships using the APOC library.
For example, you have the following test data:
MERGE p1 = (R:react {name:'react_1'})-[:`part-of`] ->(:pathway {name: 'pathway_1'})
MERGE p2 = (:mol {name: 'mol_1'})-[:`consumed-by`]->(R)
MERGE p3 = (:mol {name: 'mol_2'})-[:`consumed-by`]->(R)
MERGE p4 = (:mol {name: 'mol_3'})-[:`produced-by`]->(R)
RETURN *
Then you can try the following query:
MATCH (R:react)
MATCH (R)-[rp:`part-of`]-(p:pathway)
MATCH (m:mol)-[mr]-(R)
WITH p, m, mr,
CASE WHEN type(mr) = 'consumed-by'
THEN {from: p, type: "input", props: properties(mr), to: m}
WHEN type(mr) = 'produced-by'
THEN {from: m, type: "output", props: properties(mr), to: p}
END AS vRel
WITH vRel WHERE vRel IS NOT NULL
CALL apoc.create.vRelationship(
vRel.from,
vRel.type,
vRel.props,
vRel.to
) YIELD rel
RETURN vRel.from, rel, vRel.to
What will give the following result:

Neo4j cypher: Find all paths till node of certain type

In Neo4j I have stored data with nodes of type A and B. Between 2 nodes A there could be many nodes of type B. I would like to fetch first node of type A for each path outgoing from a given node A. I post example structure below.
/->A2->A3
A1-->A4->A5
\->B1->A6
For input: A1, I would like my query to return only A2, A4 and A6.
Query that I'm using right now is below:
MATCH p=(source:Node ) - [:relation*] -> (target:Node) WHERE
source.name = "A1" AND target.type = "A" RETURN target
However it returns nodes A3 and A5 which I want to get rid of.
I have used this sample data set to reproduce your scenario:
create (root:Node {name : "A1", type: "A"})-[:LINKED_TO]->(:Node{name : "A2", type: "A"})-[:LINKED_TO]->(:Node{name : "A3", type: "A"}),
(root)-[:LINKED_TO]->(:Node{name : "A4", type: "A"})-[:LINKED_TO]->(:Node{name : "A5", type: "A"}),
(root)-[:LINKED_TO]->(:Node{name : "B1", type: "B"})-[:LINKED_TO]->(:Node{name : "A6", type: "A"})
Then, this query, using filter() function:
// MATCH all paths between source and target, starting from 2 hops.
// target node should be the last node of the path.
MATCH p=(source:Node)-[:LINKED_TO*]->(target:Node)
WHERE source.name = "A1" AND target.type = "A" AND NOT (target)-->()
// grouping by path, I have filtered the nodes of each path, getting only ones that have type = "A"
// then I get the first one by index (index [0])
WITH p, filter(node IN nodes(p)[1..] WHERE node.type = "A")[0] as firstA
// return the firstA node
RETURN firstA
The output:
╒════════════════════════╕
│"firstA" │
╞════════════════════════╡
│{"name":"A6","type":"A"}│
├────────────────────────┤
│{"name":"A4","type":"A"}│
├────────────────────────┤
│{"name":"A2","type":"A"}│
└────────────────────────┘
Tip: instead of a property named type you can add another label for each node denoting your type, like :A and :B. Remember that labels are ideal for grouping nodes into sets. Also, a node can have more than one label.

Consolidating & Collecting into one Record

I'm trying to write a cypher query where all related nodes are collected and returned under a key in a map:
{
name: 'chart',
CONTAINTED: [
{
name: 'id'
},
{
name: 'bloodpressure'
},
...
],
FOREIGNKEY: [
{
name: 'clientid'
}
]
}
I've attempted to do this with the following cypher query but it isn't quite right. Using the method below two records are returned rather than just one.
MATCH path=(table:tabPHI {name: 'client'})-[r]-(c)
WITH table as tab, type(r) as rel, collect(c) as col
CALL apoc.map.setKey(tab, rel, col) YIELD value as foo
return foo
MATCH (table:tabPHI {name: 'client'})-[r]-(c)
WITH table as tab, type(r) as rel, collect(c) as col
WITH tab, COLLECT(rel) AS keys, COLLECT(col) AS values
WITH keys(tab) as main_keys, [key IN keys(tab)|tab[key]] AS main_values, keys, values
CALL apoc.map.fromLists(main_keys + keys, main_values + values) YIELD value as foo
return foo
You're creating a single map for each relationship type in your query. You have to COLLECT(rel) at some point to get a single result for each tab.

Neocons Cypher tquery and accessing values from keys

After calling neo4j with neocons (cy/tquery conn node-query {:_nodeid _nodeid}), how do you perform accessing functions to get property values from the keys that are returned from the neo4j datastore response?
For example if this object was the response from the neo4j datastore, what neocons syntax do I use to access the value stored in key "attributes"?
[ {
"id": "letter-a",
"name": "Letter A",
"attributes": [ ... ]
}]
Currently I can only get so far as (first _response) but (get-in (first _response) [:attributes]) is giving me back nil
******************* EDIT *******************************
Here is the cypher query string I use as an argument to invoke the tquery function:
(def node-query "MATCH (n)-[attributelist:RELATIONSHIPTYPE]->(target)
RETURN n.id AS id,
n.name AS name,
COLLECT({
target : target.id
}) AS attributes;")
I don't understand what type of variable tquery returns? It looks like this object when the client displays it all the way in the browser:
[
{
"id": "node-999990a0a0a0sa0",
"name": "Node Name",
"attributes": [
{
"target": "node-id-one"
},
{
"target": "node-id-two"
},
{
"target": "node-id-two"
},
{
"target": "node-id-two"
},
{
"target": "node-id-three"
}
]
}
]
But I want to intercept what is returned from the tquery before the clojure server delivers it to the client and I want to manipulate the array value of the key "attributes" so I can run a reduce (tally) report before I deliver a rebuilt object response to the client.
{
...
"attributes" : {
"node-id-one" : 1,
"node-id-two" : 3,
"node-id-three" : 1
}
}
But I am having trouble because I do not know the syntax to access the "attributes" key from the object that is returned from the tquery
Sorry I don't understand your question. Which query did you run with tquery?
Usually you return the data you're interested in directly from the query.
e.g
MATCH (p:Person)-[:ACTED_IN]->(m)
WHERE p.name = "Tom Hanks"
RETURN m.title, m.released`
Otherwise you'd have to requery using a label+unique-property
MATCH (m:Movie)
WHERE m.title = "The Matrix"
RETURN m.title, m.released`
or node-id match.
MATCH (m:Movie)
WHERE id(m) = 123
RETURN m.title, m.released`
You usually would use parameters instead of literal values, i.e. {name}, {title}, {id}.
Update
I think for intercepting you would have to look into the neocons implementation.
Note: there is no clojure server, it's a Neo4j server with an http endpoint.
You should be able to do what you want (almost) in cypher.
MATCH (n)-[:RELATIONSHIPTYPE]->(target)
WITH n, target.id as target, count(*) as c
RETURN n.id as id, n.name as name, collect([target,c]) as targets;
Unfortunately right now there are no dynamic map-keys in Cypher, so a tuple-collection will have to do.
PS
You should use a label at least for your n (and optionally target) nodes.

Resources